@@ -223,6 +223,55 @@ static u32 sp5100_tco_read_pm_reg32(u8 index)
223223 return val ;
224224}
225225
226+ static u32 sp5100_tco_request_region (struct device * dev ,
227+ u32 mmio_addr ,
228+ const char * dev_name )
229+ {
230+ if (!devm_request_mem_region (dev , mmio_addr , SP5100_WDT_MEM_MAP_SIZE ,
231+ dev_name )) {
232+ dev_dbg (dev , "MMIO address 0x%08x already in use\n" , mmio_addr );
233+ return 0 ;
234+ }
235+
236+ return mmio_addr ;
237+ }
238+
239+ static u32 sp5100_tco_prepare_base (struct sp5100_tco * tco ,
240+ u32 mmio_addr ,
241+ u32 alt_mmio_addr ,
242+ const char * dev_name )
243+ {
244+ struct device * dev = tco -> wdd .parent ;
245+
246+ dev_dbg (dev , "Got 0x%08x from SBResource_MMIO register\n" , mmio_addr );
247+
248+ if (!mmio_addr && !alt_mmio_addr )
249+ return - ENODEV ;
250+
251+ /* Check for MMIO address and alternate MMIO address conflicts */
252+ if (mmio_addr )
253+ mmio_addr = sp5100_tco_request_region (dev , mmio_addr , dev_name );
254+
255+ if (!mmio_addr && alt_mmio_addr )
256+ mmio_addr = sp5100_tco_request_region (dev , alt_mmio_addr , dev_name );
257+
258+ if (!mmio_addr ) {
259+ dev_err (dev , "Failed to reserve MMIO or alternate MMIO region\n" );
260+ return - EBUSY ;
261+ }
262+
263+ tco -> tcobase = devm_ioremap (dev , mmio_addr , SP5100_WDT_MEM_MAP_SIZE );
264+ if (!tco -> tcobase ) {
265+ dev_err (dev , "MMIO address 0x%08x failed mapping\n" , mmio_addr );
266+ devm_release_mem_region (dev , mmio_addr , SP5100_WDT_MEM_MAP_SIZE );
267+ return - ENOMEM ;
268+ }
269+
270+ dev_info (dev , "Using 0x%08x for watchdog MMIO address\n" , mmio_addr );
271+
272+ return 0 ;
273+ }
274+
226275static int sp5100_tco_timer_init (struct sp5100_tco * tco )
227276{
228277 struct watchdog_device * wdd = & tco -> wdd ;
@@ -264,6 +313,7 @@ static int sp5100_tco_setupdevice(struct device *dev,
264313 struct sp5100_tco * tco = watchdog_get_drvdata (wdd );
265314 const char * dev_name ;
266315 u32 mmio_addr = 0 , val ;
316+ u32 alt_mmio_addr = 0 ;
267317 int ret ;
268318
269319 /* Request the IO ports used by this driver */
@@ -282,11 +332,32 @@ static int sp5100_tco_setupdevice(struct device *dev,
282332 dev_name = SP5100_DEVNAME ;
283333 mmio_addr = sp5100_tco_read_pm_reg32 (SP5100_PM_WATCHDOG_BASE ) &
284334 0xfffffff8 ;
335+
336+ /*
337+ * Secondly, find the watchdog timer MMIO address
338+ * from SBResource_MMIO register.
339+ */
340+
341+ /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
342+ pci_read_config_dword (sp5100_tco_pci ,
343+ SP5100_SB_RESOURCE_MMIO_BASE ,
344+ & val );
345+
346+ /* Verify MMIO is enabled and using bar0 */
347+ if ((val & SB800_ACPI_MMIO_MASK ) == SB800_ACPI_MMIO_DECODE_EN )
348+ alt_mmio_addr = (val & ~0xfff ) + SB800_PM_WDT_MMIO_OFFSET ;
285349 break ;
286350 case sb800 :
287351 dev_name = SB800_DEVNAME ;
288352 mmio_addr = sp5100_tco_read_pm_reg32 (SB800_PM_WATCHDOG_BASE ) &
289353 0xfffffff8 ;
354+
355+ /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
356+ val = sp5100_tco_read_pm_reg32 (SB800_PM_ACPI_MMIO_EN );
357+
358+ /* Verify MMIO is enabled and using bar0 */
359+ if ((val & SB800_ACPI_MMIO_MASK ) == SB800_ACPI_MMIO_DECODE_EN )
360+ alt_mmio_addr = (val & ~0xfff ) + SB800_PM_WDT_MMIO_OFFSET ;
290361 break ;
291362 case efch :
292363 dev_name = SB800_DEVNAME ;
@@ -305,87 +376,23 @@ static int sp5100_tco_setupdevice(struct device *dev,
305376 val = sp5100_tco_read_pm_reg8 (EFCH_PM_DECODEEN );
306377 if (val & EFCH_PM_DECODEEN_WDT_TMREN )
307378 mmio_addr = EFCH_PM_WDT_ADDR ;
379+
380+ val = sp5100_tco_read_pm_reg8 (EFCH_PM_ISACONTROL );
381+ if (val & EFCH_PM_ISACONTROL_MMIOEN )
382+ alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
383+ EFCH_PM_ACPI_MMIO_WDT_OFFSET ;
308384 break ;
309385 default :
310386 return - ENODEV ;
311387 }
312388
313- /* Check MMIO address conflict */
314- if (!mmio_addr ||
315- !devm_request_mem_region (dev , mmio_addr , SP5100_WDT_MEM_MAP_SIZE ,
316- dev_name )) {
317- if (mmio_addr )
318- dev_dbg (dev , "MMIO address 0x%08x already in use\n" ,
319- mmio_addr );
320- switch (tco -> tco_reg_layout ) {
321- case sp5100 :
322- /*
323- * Secondly, Find the watchdog timer MMIO address
324- * from SBResource_MMIO register.
325- */
326- /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
327- pci_read_config_dword (sp5100_tco_pci ,
328- SP5100_SB_RESOURCE_MMIO_BASE ,
329- & mmio_addr );
330- if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
331- SB800_ACPI_MMIO_SEL )) !=
332- SB800_ACPI_MMIO_DECODE_EN ) {
333- ret = - ENODEV ;
334- goto unreg_region ;
335- }
336- mmio_addr &= ~0xFFF ;
337- mmio_addr += SB800_PM_WDT_MMIO_OFFSET ;
338- break ;
339- case sb800 :
340- /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
341- mmio_addr =
342- sp5100_tco_read_pm_reg32 (SB800_PM_ACPI_MMIO_EN );
343- if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
344- SB800_ACPI_MMIO_SEL )) !=
345- SB800_ACPI_MMIO_DECODE_EN ) {
346- ret = - ENODEV ;
347- goto unreg_region ;
348- }
349- mmio_addr &= ~0xFFF ;
350- mmio_addr += SB800_PM_WDT_MMIO_OFFSET ;
351- break ;
352- case efch :
353- val = sp5100_tco_read_pm_reg8 (EFCH_PM_ISACONTROL );
354- if (!(val & EFCH_PM_ISACONTROL_MMIOEN )) {
355- ret = - ENODEV ;
356- goto unreg_region ;
357- }
358- mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
359- EFCH_PM_ACPI_MMIO_WDT_OFFSET ;
360- break ;
361- }
362- dev_dbg (dev , "Got 0x%08x from SBResource_MMIO register\n" ,
363- mmio_addr );
364- if (!devm_request_mem_region (dev , mmio_addr ,
365- SP5100_WDT_MEM_MAP_SIZE ,
366- dev_name )) {
367- dev_dbg (dev , "MMIO address 0x%08x already in use\n" ,
368- mmio_addr );
369- ret = - EBUSY ;
370- goto unreg_region ;
371- }
372- }
373-
374- tco -> tcobase = devm_ioremap (dev , mmio_addr , SP5100_WDT_MEM_MAP_SIZE );
375- if (!tco -> tcobase ) {
376- dev_err (dev , "failed to get tcobase address\n" );
377- ret = - ENOMEM ;
378- goto unreg_region ;
389+ ret = sp5100_tco_prepare_base (tco , mmio_addr , alt_mmio_addr , dev_name );
390+ if (!ret ) {
391+ /* Setup the watchdog timer */
392+ tco_timer_enable (tco );
393+ ret = sp5100_tco_timer_init (tco );
379394 }
380395
381- dev_info (dev , "Using 0x%08x for watchdog MMIO address\n" , mmio_addr );
382-
383- /* Setup the watchdog timer */
384- tco_timer_enable (tco );
385-
386- ret = sp5100_tco_timer_init (tco );
387-
388- unreg_region :
389396 release_region (SP5100_IO_PM_INDEX_REG , SP5100_PM_IOPORTS_SIZE );
390397 return ret ;
391398}
0 commit comments