Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: pxa25x_udc: use readl/writel for mmio

This converts the pxa25x udc driver to use readl/writel as normal
driver should do, rather than dereferencing __iomem pointers
themselves.

Based on the earlier preparation work, we can now also pass
the register start in the device pointer so we no longer need
the global variable.

The unclear part here is for IXP4xx, which supports both big-endian
and little-endian configurations. So far, the driver has done
no byteswap in either case. I suspect that is wrong and it would
actually need to swap in one or the other case, but I don't know
which. It's also possible that there is some magic setting in
the chip that makes the endianess of the MMIO register match the
CPU, and in that case, the code actually does the right thing
for all configurations, both before and after this patch.

Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Felipe Balbi <balbi@kernel.org>

authored by

Arnd Bergmann and committed by
Felipe Balbi
65bc0fba a77af20e

+40 -22
+39 -22
drivers/usb/gadget/udc/pxa25x_udc.c
··· 52 52 #include <mach/lubbock.h> 53 53 #endif 54 54 55 - static void __iomem *pxa25x_udc_reg_base; 56 - #define __UDC_REG(x) (*((volatile u32 *)(pxa25x_udc_reg_base + (x)))) 57 - 58 55 #define UDCCR 0x0000 /* UDC Control Register */ 59 56 #define UDC_RES1 0x0004 /* UDC Undocumented - Reserved1 */ 60 57 #define UDC_RES2 0x0008 /* UDC Undocumented - Reserved2 */ ··· 289 292 mach->udc_command(PXA2XX_UDC_CMD_CONNECT); 290 293 } 291 294 292 - static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 uicr) 295 + #if defined(CONFIG_ARCH_IXP4XX) && defined(CONFIG_CPU_BIG_ENDIAN) 296 + /* 297 + * not sure if this is the correct behavior on ixp4xx in both 298 + * bit-endian and little-endian modes, but it's what the driver 299 + * has always done using direct pointer dereferences: 300 + * We assume that there is a byteswap done in hardware at the 301 + * MMIO register that matches what the CPU setting is, so we 302 + * never swap in software. 303 + */ 304 + static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 val) 293 305 { 294 - __UDC_REG(reg) = uicr; 306 + iowrite32be(val, dev->regs + reg); 295 307 } 296 308 297 309 static inline u32 udc_get_reg(struct pxa25x_udc *dev, u32 reg) 298 310 { 299 - return __UDC_REG(reg); 311 + return ioread32be(dev->regs + reg); 300 312 } 313 + #else 314 + static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 val) 315 + { 316 + writel(val, dev->regs + reg); 317 + } 318 + 319 + static inline u32 udc_get_reg(struct pxa25x_udc *dev, u32 reg) 320 + { 321 + return readl(dev->regs + reg); 322 + } 323 + #endif 301 324 302 325 static void pio_irq_enable(struct pxa25x_ep *ep) 303 326 { ··· 354 337 355 338 static inline void udc_set_mask_UDCCR(struct pxa25x_udc *dev, int mask) 356 339 { 357 - u32 udccr = __UDC_REG(UDCCR); 340 + u32 udccr = udc_get_reg(dev, UDCCR); 358 341 359 - __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); 342 + udc_set_reg(dev, (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS), UDCCR); 360 343 } 361 344 362 345 static inline void udc_clear_mask_UDCCR(struct pxa25x_udc *dev, int mask) 363 346 { 364 - u32 udccr = __UDC_REG(UDCCR); 347 + u32 udccr = udc_get_reg(dev, UDCCR); 365 348 366 - __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); 349 + udc_set_reg(dev, (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS), UDCCR); 367 350 } 368 351 369 352 static inline void udc_ack_int_UDCCR(struct pxa25x_udc *dev, int mask) 370 353 { 371 354 /* udccr contains the bits we dont want to change */ 372 - u32 udccr = __UDC_REG(UDCCR) & UDCCR_MASK_BITS; 355 + u32 udccr = udc_get_reg(dev, UDCCR) & UDCCR_MASK_BITS; 373 356 374 - __UDC_REG(UDCCR) = udccr | (mask & ~UDCCR_MASK_BITS); 357 + udc_set_reg(dev, udccr | (mask & ~UDCCR_MASK_BITS), UDCCR); 375 358 } 376 359 377 360 static inline u32 udc_ep_get_UDCCS(struct pxa25x_ep *ep) 378 361 { 379 - return __UDC_REG(ep->regoff_udccs); 362 + return udc_get_reg(ep->dev, ep->regoff_udccs); 380 363 } 381 364 382 365 static inline void udc_ep_set_UDCCS(struct pxa25x_ep *ep, u32 data) 383 366 { 384 - __UDC_REG(ep->regoff_udccs) = data; 367 + udc_set_reg(ep->dev, data, ep->regoff_udccs); 385 368 } 386 369 387 370 static inline u32 udc_ep0_get_UDCCS(struct pxa25x_udc *dev) 388 371 { 389 - return __UDC_REG(UDCCS0); 372 + return udc_get_reg(dev, UDCCS0); 390 373 } 391 374 392 375 static inline void udc_ep0_set_UDCCS(struct pxa25x_udc *dev, u32 data) 393 376 { 394 - __UDC_REG(UDCCS0) = data; 377 + udc_set_reg(dev, data, UDCCS0); 395 378 } 396 379 397 380 static inline u32 udc_ep_get_UDDR(struct pxa25x_ep *ep) 398 381 { 399 - return __UDC_REG(ep->regoff_uddr); 382 + return udc_get_reg(ep->dev, ep->regoff_uddr); 400 383 } 401 384 402 385 static inline void udc_ep_set_UDDR(struct pxa25x_ep *ep, u32 data) 403 386 { 404 - __UDC_REG(ep->regoff_uddr) = data; 387 + udc_set_reg(ep->dev, data, ep->regoff_uddr); 405 388 } 406 389 407 390 static inline u32 udc_ep_get_UBCR(struct pxa25x_ep *ep) 408 391 { 409 - return __UDC_REG(ep->regoff_ubcr); 392 + return udc_get_reg(ep->dev, ep->regoff_ubcr); 410 393 } 411 394 412 395 /* ··· 2386 2369 return -ENODEV; 2387 2370 2388 2371 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2389 - pxa25x_udc_reg_base = devm_ioremap_resource(&pdev->dev, res); 2390 - if (IS_ERR(pxa25x_udc_reg_base)) 2391 - return PTR_ERR(pxa25x_udc_reg_base); 2372 + dev->regs = devm_ioremap_resource(&pdev->dev, res); 2373 + if (IS_ERR(dev->regs)) 2374 + return PTR_ERR(dev->regs); 2392 2375 2393 2376 dev->clk = devm_clk_get(&pdev->dev, NULL); 2394 2377 if (IS_ERR(dev->clk))
+1
drivers/usb/gadget/udc/pxa25x_udc.h
··· 125 125 #ifdef CONFIG_USB_GADGET_DEBUG_FS 126 126 struct dentry *debugfs_udc; 127 127 #endif 128 + void __iomem *regs; 128 129 }; 129 130 #define to_pxa25x(g) (container_of((g), struct pxa25x_udc, gadget)) 130 131