1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * arch/arm/mach-ep93xx/core.c |
4 | * Core routines for Cirrus EP93xx chips. |
5 | * |
6 | * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> |
7 | * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> |
8 | * |
9 | * Thanks go to Michael Burian and Ray Lehtiniemi for their key |
10 | * role in the ep93xx linux community. |
11 | */ |
12 | |
13 | #define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt |
14 | |
15 | #include <linux/kernel.h> |
16 | #include <linux/init.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/interrupt.h> |
19 | #include <linux/dma-mapping.h> |
20 | #include <linux/sys_soc.h> |
21 | #include <linux/irq.h> |
22 | #include <linux/io.h> |
23 | #include <linux/gpio.h> |
24 | #include <linux/leds.h> |
25 | #include <linux/uaccess.h> |
26 | #include <linux/termios.h> |
27 | #include <linux/amba/bus.h> |
28 | #include <linux/amba/serial.h> |
29 | #include <linux/mtd/physmap.h> |
30 | #include <linux/i2c.h> |
31 | #include <linux/gpio/machine.h> |
32 | #include <linux/spi/spi.h> |
33 | #include <linux/export.h> |
34 | #include <linux/irqchip/arm-vic.h> |
35 | #include <linux/reboot.h> |
36 | #include <linux/usb/ohci_pdriver.h> |
37 | #include <linux/random.h> |
38 | |
39 | #include "hardware.h" |
40 | #include <linux/platform_data/video-ep93xx.h> |
41 | #include <linux/platform_data/keypad-ep93xx.h> |
42 | #include <linux/platform_data/spi-ep93xx.h> |
43 | #include <linux/soc/cirrus/ep93xx.h> |
44 | |
45 | #include "gpio-ep93xx.h" |
46 | |
47 | #include <asm/mach/arch.h> |
48 | #include <asm/mach/map.h> |
49 | |
50 | #include "soc.h" |
51 | #include "irqs.h" |
52 | |
53 | /************************************************************************* |
54 | * Static I/O mappings that are needed for all EP93xx platforms |
55 | *************************************************************************/ |
56 | static struct map_desc ep93xx_io_desc[] __initdata = { |
57 | { |
58 | .virtual = EP93XX_AHB_VIRT_BASE, |
59 | .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE), |
60 | .length = EP93XX_AHB_SIZE, |
61 | .type = MT_DEVICE, |
62 | }, { |
63 | .virtual = EP93XX_APB_VIRT_BASE, |
64 | .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE), |
65 | .length = EP93XX_APB_SIZE, |
66 | .type = MT_DEVICE, |
67 | }, |
68 | }; |
69 | |
70 | void __init ep93xx_map_io(void) |
71 | { |
72 | iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); |
73 | } |
74 | |
75 | /************************************************************************* |
76 | * EP93xx IRQ handling |
77 | *************************************************************************/ |
78 | void __init ep93xx_init_irq(void) |
79 | { |
80 | vic_init(EP93XX_VIC1_BASE, IRQ_EP93XX_VIC0, EP93XX_VIC1_VALID_IRQ_MASK, resume_sources: 0); |
81 | vic_init(EP93XX_VIC2_BASE, IRQ_EP93XX_VIC1, EP93XX_VIC2_VALID_IRQ_MASK, resume_sources: 0); |
82 | } |
83 | |
84 | |
85 | /************************************************************************* |
86 | * EP93xx System Controller Software Locked register handling |
87 | *************************************************************************/ |
88 | |
89 | /* |
90 | * syscon_swlock prevents anything else from writing to the syscon |
91 | * block while a software locked register is being written. |
92 | */ |
93 | static DEFINE_SPINLOCK(syscon_swlock); |
94 | |
95 | void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) |
96 | { |
97 | unsigned long flags; |
98 | |
99 | spin_lock_irqsave(&syscon_swlock, flags); |
100 | |
101 | __raw_writel(val: 0xaa, EP93XX_SYSCON_SWLOCK); |
102 | __raw_writel(val, addr: reg); |
103 | |
104 | spin_unlock_irqrestore(lock: &syscon_swlock, flags); |
105 | } |
106 | |
107 | void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) |
108 | { |
109 | unsigned long flags; |
110 | unsigned int val; |
111 | |
112 | spin_lock_irqsave(&syscon_swlock, flags); |
113 | |
114 | val = __raw_readl(EP93XX_SYSCON_DEVCFG); |
115 | val &= ~clear_bits; |
116 | val |= set_bits; |
117 | __raw_writel(val: 0xaa, EP93XX_SYSCON_SWLOCK); |
118 | __raw_writel(val, EP93XX_SYSCON_DEVCFG); |
119 | |
120 | spin_unlock_irqrestore(lock: &syscon_swlock, flags); |
121 | } |
122 | |
123 | /** |
124 | * ep93xx_chip_revision() - returns the EP93xx chip revision |
125 | * |
126 | * See "platform.h" for more information. |
127 | */ |
128 | unsigned int ep93xx_chip_revision(void) |
129 | { |
130 | unsigned int v; |
131 | |
132 | v = __raw_readl(EP93XX_SYSCON_SYSCFG); |
133 | v &= EP93XX_SYSCON_SYSCFG_REV_MASK; |
134 | v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; |
135 | return v; |
136 | } |
137 | EXPORT_SYMBOL_GPL(ep93xx_chip_revision); |
138 | |
139 | /************************************************************************* |
140 | * EP93xx GPIO |
141 | *************************************************************************/ |
142 | static struct resource ep93xx_gpio_resource[] = { |
143 | DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc), |
144 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO_AB), |
145 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO0MUX), |
146 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO1MUX), |
147 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO2MUX), |
148 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO3MUX), |
149 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO4MUX), |
150 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO5MUX), |
151 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO6MUX), |
152 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO7MUX), |
153 | }; |
154 | |
155 | static struct platform_device ep93xx_gpio_device = { |
156 | .name = "gpio-ep93xx" , |
157 | .id = -1, |
158 | .num_resources = ARRAY_SIZE(ep93xx_gpio_resource), |
159 | .resource = ep93xx_gpio_resource, |
160 | }; |
161 | |
162 | /************************************************************************* |
163 | * EP93xx peripheral handling |
164 | *************************************************************************/ |
165 | #define EP93XX_UART_MCR_OFFSET (0x0100) |
166 | |
167 | static void ep93xx_uart_set_mctrl(struct amba_device *dev, |
168 | void __iomem *base, unsigned int mctrl) |
169 | { |
170 | unsigned int mcr; |
171 | |
172 | mcr = 0; |
173 | if (mctrl & TIOCM_RTS) |
174 | mcr |= 2; |
175 | if (mctrl & TIOCM_DTR) |
176 | mcr |= 1; |
177 | |
178 | __raw_writel(val: mcr, addr: base + EP93XX_UART_MCR_OFFSET); |
179 | } |
180 | |
181 | static struct amba_pl010_data ep93xx_uart_data = { |
182 | .set_mctrl = ep93xx_uart_set_mctrl, |
183 | }; |
184 | |
185 | static AMBA_APB_DEVICE(uart1, "apb:uart1" , 0x00041010, EP93XX_UART1_PHYS_BASE, |
186 | { IRQ_EP93XX_UART1 }, &ep93xx_uart_data); |
187 | |
188 | static AMBA_APB_DEVICE(uart2, "apb:uart2" , 0x00041010, EP93XX_UART2_PHYS_BASE, |
189 | { IRQ_EP93XX_UART2 }, NULL); |
190 | |
191 | static AMBA_APB_DEVICE(uart3, "apb:uart3" , 0x00041010, EP93XX_UART3_PHYS_BASE, |
192 | { IRQ_EP93XX_UART3 }, &ep93xx_uart_data); |
193 | |
194 | static struct resource ep93xx_rtc_resource[] = { |
195 | DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c), |
196 | }; |
197 | |
198 | static struct platform_device ep93xx_rtc_device = { |
199 | .name = "ep93xx-rtc" , |
200 | .id = -1, |
201 | .num_resources = ARRAY_SIZE(ep93xx_rtc_resource), |
202 | .resource = ep93xx_rtc_resource, |
203 | }; |
204 | |
205 | /************************************************************************* |
206 | * EP93xx OHCI USB Host |
207 | *************************************************************************/ |
208 | |
209 | static struct clk *ep93xx_ohci_host_clock; |
210 | |
211 | static int ep93xx_ohci_power_on(struct platform_device *pdev) |
212 | { |
213 | if (!ep93xx_ohci_host_clock) { |
214 | ep93xx_ohci_host_clock = devm_clk_get(dev: &pdev->dev, NULL); |
215 | if (IS_ERR(ptr: ep93xx_ohci_host_clock)) |
216 | return PTR_ERR(ptr: ep93xx_ohci_host_clock); |
217 | } |
218 | |
219 | return clk_prepare_enable(clk: ep93xx_ohci_host_clock); |
220 | } |
221 | |
222 | static void ep93xx_ohci_power_off(struct platform_device *pdev) |
223 | { |
224 | clk_disable(clk: ep93xx_ohci_host_clock); |
225 | } |
226 | |
227 | static struct usb_ohci_pdata ep93xx_ohci_pdata = { |
228 | .power_on = ep93xx_ohci_power_on, |
229 | .power_off = ep93xx_ohci_power_off, |
230 | .power_suspend = ep93xx_ohci_power_off, |
231 | }; |
232 | |
233 | static struct resource ep93xx_ohci_resources[] = { |
234 | DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), |
235 | DEFINE_RES_IRQ(IRQ_EP93XX_USB), |
236 | }; |
237 | |
238 | static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); |
239 | |
240 | static struct platform_device ep93xx_ohci_device = { |
241 | .name = "ohci-platform" , |
242 | .id = -1, |
243 | .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), |
244 | .resource = ep93xx_ohci_resources, |
245 | .dev = { |
246 | .dma_mask = &ep93xx_ohci_dma_mask, |
247 | .coherent_dma_mask = DMA_BIT_MASK(32), |
248 | .platform_data = &ep93xx_ohci_pdata, |
249 | }, |
250 | }; |
251 | |
252 | /************************************************************************* |
253 | * EP93xx physmap'ed flash |
254 | *************************************************************************/ |
255 | static struct physmap_flash_data ep93xx_flash_data; |
256 | |
257 | static struct resource ep93xx_flash_resource = { |
258 | .flags = IORESOURCE_MEM, |
259 | }; |
260 | |
261 | static struct platform_device ep93xx_flash = { |
262 | .name = "physmap-flash" , |
263 | .id = 0, |
264 | .dev = { |
265 | .platform_data = &ep93xx_flash_data, |
266 | }, |
267 | .num_resources = 1, |
268 | .resource = &ep93xx_flash_resource, |
269 | }; |
270 | |
271 | /** |
272 | * ep93xx_register_flash() - Register the external flash device. |
273 | * @width: bank width in octets |
274 | * @start: resource start address |
275 | * @size: resource size |
276 | */ |
277 | void __init ep93xx_register_flash(unsigned int width, |
278 | resource_size_t start, resource_size_t size) |
279 | { |
280 | ep93xx_flash_data.width = width; |
281 | |
282 | ep93xx_flash_resource.start = start; |
283 | ep93xx_flash_resource.end = start + size - 1; |
284 | |
285 | platform_device_register(&ep93xx_flash); |
286 | } |
287 | |
288 | |
289 | /************************************************************************* |
290 | * EP93xx ethernet peripheral handling |
291 | *************************************************************************/ |
292 | static struct ep93xx_eth_data ep93xx_eth_data; |
293 | |
294 | static struct resource ep93xx_eth_resource[] = { |
295 | DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000), |
296 | DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET), |
297 | }; |
298 | |
299 | static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); |
300 | |
301 | static struct platform_device ep93xx_eth_device = { |
302 | .name = "ep93xx-eth" , |
303 | .id = -1, |
304 | .dev = { |
305 | .platform_data = &ep93xx_eth_data, |
306 | .coherent_dma_mask = DMA_BIT_MASK(32), |
307 | .dma_mask = &ep93xx_eth_dma_mask, |
308 | }, |
309 | .num_resources = ARRAY_SIZE(ep93xx_eth_resource), |
310 | .resource = ep93xx_eth_resource, |
311 | }; |
312 | |
313 | /** |
314 | * ep93xx_register_eth - Register the built-in ethernet platform device. |
315 | * @data: platform specific ethernet configuration (__initdata) |
316 | * @copy_addr: flag indicating that the MAC address should be copied |
317 | * from the IndAd registers (as programmed by the bootloader) |
318 | */ |
319 | void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) |
320 | { |
321 | if (copy_addr) |
322 | memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6); |
323 | |
324 | ep93xx_eth_data = *data; |
325 | platform_device_register(&ep93xx_eth_device); |
326 | } |
327 | |
328 | |
329 | /************************************************************************* |
330 | * EP93xx i2c peripheral handling |
331 | *************************************************************************/ |
332 | |
333 | /* All EP93xx devices use the same two GPIO pins for I2C bit-banging */ |
334 | static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = { |
335 | .dev_id = "i2c-gpio.0" , |
336 | .table = { |
337 | /* Use local offsets on gpiochip/port "G" */ |
338 | GPIO_LOOKUP_IDX("G" , 1, NULL, 0, |
339 | GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), |
340 | GPIO_LOOKUP_IDX("G" , 0, NULL, 1, |
341 | GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), |
342 | }, |
343 | }; |
344 | |
345 | static struct platform_device ep93xx_i2c_device = { |
346 | .name = "i2c-gpio" , |
347 | .id = 0, |
348 | .dev = { |
349 | .platform_data = NULL, |
350 | }, |
351 | }; |
352 | |
353 | /** |
354 | * ep93xx_register_i2c - Register the i2c platform device. |
355 | * @devices: platform specific i2c bus device information (__initdata) |
356 | * @num: the number of devices on the i2c bus |
357 | */ |
358 | void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) |
359 | { |
360 | /* |
361 | * FIXME: this just sets the two pins as non-opendrain, as no |
362 | * platforms tries to do that anyway. Flag the applicable lines |
363 | * as open drain in the GPIO_LOOKUP above and the driver or |
364 | * gpiolib will handle open drain/open drain emulation as need |
365 | * be. Right now i2c-gpio emulates open drain which is not |
366 | * optimal. |
367 | */ |
368 | __raw_writel(val: (0 << 1) | (0 << 0), |
369 | EP93XX_GPIO_EEDRIVE); |
370 | |
371 | i2c_register_board_info(busnum: 0, info: devices, n: num); |
372 | gpiod_add_lookup_table(table: &ep93xx_i2c_gpiod_table); |
373 | platform_device_register(&ep93xx_i2c_device); |
374 | } |
375 | |
376 | /************************************************************************* |
377 | * EP93xx SPI peripheral handling |
378 | *************************************************************************/ |
379 | static struct ep93xx_spi_info ep93xx_spi_master_data; |
380 | |
381 | static struct resource ep93xx_spi_resources[] = { |
382 | DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18), |
383 | DEFINE_RES_IRQ(IRQ_EP93XX_SSP), |
384 | }; |
385 | |
386 | static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32); |
387 | |
388 | static struct platform_device ep93xx_spi_device = { |
389 | .name = "ep93xx-spi" , |
390 | .id = 0, |
391 | .dev = { |
392 | .platform_data = &ep93xx_spi_master_data, |
393 | .coherent_dma_mask = DMA_BIT_MASK(32), |
394 | .dma_mask = &ep93xx_spi_dma_mask, |
395 | }, |
396 | .num_resources = ARRAY_SIZE(ep93xx_spi_resources), |
397 | .resource = ep93xx_spi_resources, |
398 | }; |
399 | |
400 | /** |
401 | * ep93xx_register_spi() - registers spi platform device |
402 | * @info: ep93xx board specific spi master info (__initdata) |
403 | * @devices: SPI devices to register (__initdata) |
404 | * @num: number of SPI devices to register |
405 | * |
406 | * This function registers platform device for the EP93xx SPI controller and |
407 | * also makes sure that SPI pins are muxed so that I2S is not using those pins. |
408 | */ |
409 | void __init ep93xx_register_spi(struct ep93xx_spi_info *info, |
410 | struct spi_board_info *devices, int num) |
411 | { |
412 | /* |
413 | * When SPI is used, we need to make sure that I2S is muxed off from |
414 | * SPI pins. |
415 | */ |
416 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP); |
417 | |
418 | ep93xx_spi_master_data = *info; |
419 | spi_register_board_info(info: devices, n: num); |
420 | platform_device_register(&ep93xx_spi_device); |
421 | } |
422 | |
423 | /************************************************************************* |
424 | * EP93xx LEDs |
425 | *************************************************************************/ |
426 | static const struct gpio_led ep93xx_led_pins[] __initconst = { |
427 | { |
428 | .name = "platform:grled" , |
429 | }, { |
430 | .name = "platform:rdled" , |
431 | }, |
432 | }; |
433 | |
434 | static const struct gpio_led_platform_data ep93xx_led_data __initconst = { |
435 | .num_leds = ARRAY_SIZE(ep93xx_led_pins), |
436 | .leds = ep93xx_led_pins, |
437 | }; |
438 | |
439 | static struct gpiod_lookup_table ep93xx_leds_gpio_table = { |
440 | .dev_id = "leds-gpio" , |
441 | .table = { |
442 | /* Use local offsets on gpiochip/port "E" */ |
443 | GPIO_LOOKUP_IDX("E" , 0, NULL, 0, GPIO_ACTIVE_HIGH), |
444 | GPIO_LOOKUP_IDX("E" , 1, NULL, 1, GPIO_ACTIVE_HIGH), |
445 | { } |
446 | }, |
447 | }; |
448 | |
449 | /************************************************************************* |
450 | * EP93xx pwm peripheral handling |
451 | *************************************************************************/ |
452 | static struct resource ep93xx_pwm0_resource[] = { |
453 | DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10), |
454 | }; |
455 | |
456 | static struct platform_device ep93xx_pwm0_device = { |
457 | .name = "ep93xx-pwm" , |
458 | .id = 0, |
459 | .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource), |
460 | .resource = ep93xx_pwm0_resource, |
461 | }; |
462 | |
463 | static struct resource ep93xx_pwm1_resource[] = { |
464 | DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10), |
465 | }; |
466 | |
467 | static struct platform_device ep93xx_pwm1_device = { |
468 | .name = "ep93xx-pwm" , |
469 | .id = 1, |
470 | .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource), |
471 | .resource = ep93xx_pwm1_resource, |
472 | }; |
473 | |
474 | void __init ep93xx_register_pwm(int pwm0, int pwm1) |
475 | { |
476 | if (pwm0) |
477 | platform_device_register(&ep93xx_pwm0_device); |
478 | |
479 | /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */ |
480 | if (pwm1) |
481 | platform_device_register(&ep93xx_pwm1_device); |
482 | } |
483 | |
484 | int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) |
485 | { |
486 | int err; |
487 | |
488 | if (pdev->id == 0) { |
489 | err = 0; |
490 | } else if (pdev->id == 1) { |
491 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO14, |
492 | label: dev_name(dev: &pdev->dev)); |
493 | if (err) |
494 | return err; |
495 | err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, value: 0); |
496 | if (err) |
497 | goto fail; |
498 | |
499 | /* PWM 1 output on EGPIO[14] */ |
500 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG); |
501 | } else { |
502 | err = -ENODEV; |
503 | } |
504 | |
505 | return err; |
506 | |
507 | fail: |
508 | gpio_free(EP93XX_GPIO_LINE_EGPIO14); |
509 | return err; |
510 | } |
511 | EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio); |
512 | |
513 | void ep93xx_pwm_release_gpio(struct platform_device *pdev) |
514 | { |
515 | if (pdev->id == 1) { |
516 | gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14); |
517 | gpio_free(EP93XX_GPIO_LINE_EGPIO14); |
518 | |
519 | /* EGPIO[14] used for GPIO */ |
520 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG); |
521 | } |
522 | } |
523 | EXPORT_SYMBOL(ep93xx_pwm_release_gpio); |
524 | |
525 | |
526 | /************************************************************************* |
527 | * EP93xx video peripheral handling |
528 | *************************************************************************/ |
529 | static struct ep93xxfb_mach_info ep93xxfb_data; |
530 | |
531 | static struct resource ep93xx_fb_resource[] = { |
532 | DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800), |
533 | }; |
534 | |
535 | static struct platform_device ep93xx_fb_device = { |
536 | .name = "ep93xx-fb" , |
537 | .id = -1, |
538 | .dev = { |
539 | .platform_data = &ep93xxfb_data, |
540 | .coherent_dma_mask = DMA_BIT_MASK(32), |
541 | .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, |
542 | }, |
543 | .num_resources = ARRAY_SIZE(ep93xx_fb_resource), |
544 | .resource = ep93xx_fb_resource, |
545 | }; |
546 | |
547 | /* The backlight use a single register in the framebuffer's register space */ |
548 | #define EP93XX_RASTER_REG_BRIGHTNESS 0x20 |
549 | |
550 | static struct resource ep93xx_bl_resources[] = { |
551 | DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE + |
552 | EP93XX_RASTER_REG_BRIGHTNESS, 0x04), |
553 | }; |
554 | |
555 | static struct platform_device ep93xx_bl_device = { |
556 | .name = "ep93xx-bl" , |
557 | .id = -1, |
558 | .num_resources = ARRAY_SIZE(ep93xx_bl_resources), |
559 | .resource = ep93xx_bl_resources, |
560 | }; |
561 | |
562 | /** |
563 | * ep93xx_register_fb - Register the framebuffer platform device. |
564 | * @data: platform specific framebuffer configuration (__initdata) |
565 | */ |
566 | void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) |
567 | { |
568 | ep93xxfb_data = *data; |
569 | platform_device_register(&ep93xx_fb_device); |
570 | platform_device_register(&ep93xx_bl_device); |
571 | } |
572 | |
573 | |
574 | /************************************************************************* |
575 | * EP93xx matrix keypad peripheral handling |
576 | *************************************************************************/ |
577 | static struct ep93xx_keypad_platform_data ep93xx_keypad_data; |
578 | |
579 | static struct resource ep93xx_keypad_resource[] = { |
580 | DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c), |
581 | DEFINE_RES_IRQ(IRQ_EP93XX_KEY), |
582 | }; |
583 | |
584 | static struct platform_device ep93xx_keypad_device = { |
585 | .name = "ep93xx-keypad" , |
586 | .id = -1, |
587 | .dev = { |
588 | .platform_data = &ep93xx_keypad_data, |
589 | }, |
590 | .num_resources = ARRAY_SIZE(ep93xx_keypad_resource), |
591 | .resource = ep93xx_keypad_resource, |
592 | }; |
593 | |
594 | /** |
595 | * ep93xx_register_keypad - Register the keypad platform device. |
596 | * @data: platform specific keypad configuration (__initdata) |
597 | */ |
598 | void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data) |
599 | { |
600 | ep93xx_keypad_data = *data; |
601 | platform_device_register(&ep93xx_keypad_device); |
602 | } |
603 | |
604 | int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) |
605 | { |
606 | int err; |
607 | int i; |
608 | |
609 | for (i = 0; i < 8; i++) { |
610 | err = gpio_request(EP93XX_GPIO_LINE_C(i), label: dev_name(dev: &pdev->dev)); |
611 | if (err) |
612 | goto fail_gpio_c; |
613 | err = gpio_request(EP93XX_GPIO_LINE_D(i), label: dev_name(dev: &pdev->dev)); |
614 | if (err) |
615 | goto fail_gpio_d; |
616 | } |
617 | |
618 | /* Enable the keypad controller; GPIO ports C and D used for keypad */ |
619 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS | |
620 | EP93XX_SYSCON_DEVCFG_GONK); |
621 | |
622 | return 0; |
623 | |
624 | fail_gpio_d: |
625 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
626 | fail_gpio_c: |
627 | for (--i; i >= 0; --i) { |
628 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
629 | gpio_free(EP93XX_GPIO_LINE_D(i)); |
630 | } |
631 | return err; |
632 | } |
633 | EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio); |
634 | |
635 | void ep93xx_keypad_release_gpio(struct platform_device *pdev) |
636 | { |
637 | int i; |
638 | |
639 | for (i = 0; i < 8; i++) { |
640 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
641 | gpio_free(EP93XX_GPIO_LINE_D(i)); |
642 | } |
643 | |
644 | /* Disable the keypad controller; GPIO ports C and D used for GPIO */ |
645 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | |
646 | EP93XX_SYSCON_DEVCFG_GONK); |
647 | } |
648 | EXPORT_SYMBOL(ep93xx_keypad_release_gpio); |
649 | |
650 | /************************************************************************* |
651 | * EP93xx I2S audio peripheral handling |
652 | *************************************************************************/ |
653 | static struct resource ep93xx_i2s_resource[] = { |
654 | DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), |
655 | DEFINE_RES_IRQ(IRQ_EP93XX_SAI), |
656 | }; |
657 | |
658 | static struct platform_device ep93xx_i2s_device = { |
659 | .name = "ep93xx-i2s" , |
660 | .id = -1, |
661 | .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), |
662 | .resource = ep93xx_i2s_resource, |
663 | }; |
664 | |
665 | static struct platform_device ep93xx_pcm_device = { |
666 | .name = "ep93xx-pcm-audio" , |
667 | .id = -1, |
668 | }; |
669 | |
670 | void __init ep93xx_register_i2s(void) |
671 | { |
672 | platform_device_register(&ep93xx_i2s_device); |
673 | platform_device_register(&ep93xx_pcm_device); |
674 | } |
675 | |
676 | #define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ |
677 | EP93XX_SYSCON_DEVCFG_I2SONAC97) |
678 | |
679 | #define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ |
680 | EP93XX_SYSCON_I2SCLKDIV_SPOL) |
681 | |
682 | int ep93xx_i2s_acquire(void) |
683 | { |
684 | unsigned val; |
685 | |
686 | ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97, |
687 | EP93XX_SYSCON_DEVCFG_I2S_MASK); |
688 | |
689 | /* |
690 | * This is potentially racy with the clock api for i2s_mclk, sclk and |
691 | * lrclk. Since the i2s driver is the only user of those clocks we |
692 | * rely on it to prevent parallel use of this function and the |
693 | * clock api for the i2s clocks. |
694 | */ |
695 | val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); |
696 | val &= ~EP93XX_I2SCLKDIV_MASK; |
697 | val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL; |
698 | ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); |
699 | |
700 | return 0; |
701 | } |
702 | EXPORT_SYMBOL(ep93xx_i2s_acquire); |
703 | |
704 | void ep93xx_i2s_release(void) |
705 | { |
706 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); |
707 | } |
708 | EXPORT_SYMBOL(ep93xx_i2s_release); |
709 | |
710 | /************************************************************************* |
711 | * EP93xx AC97 audio peripheral handling |
712 | *************************************************************************/ |
713 | static struct resource ep93xx_ac97_resources[] = { |
714 | DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac), |
715 | DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR), |
716 | }; |
717 | |
718 | static struct platform_device ep93xx_ac97_device = { |
719 | .name = "ep93xx-ac97" , |
720 | .id = -1, |
721 | .num_resources = ARRAY_SIZE(ep93xx_ac97_resources), |
722 | .resource = ep93xx_ac97_resources, |
723 | }; |
724 | |
725 | void __init ep93xx_register_ac97(void) |
726 | { |
727 | /* |
728 | * Make sure that the AC97 pins are not used by I2S. |
729 | */ |
730 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97); |
731 | |
732 | platform_device_register(&ep93xx_ac97_device); |
733 | platform_device_register(&ep93xx_pcm_device); |
734 | } |
735 | |
736 | /************************************************************************* |
737 | * EP93xx Watchdog |
738 | *************************************************************************/ |
739 | static struct resource ep93xx_wdt_resources[] = { |
740 | DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08), |
741 | }; |
742 | |
743 | static struct platform_device ep93xx_wdt_device = { |
744 | .name = "ep93xx-wdt" , |
745 | .id = -1, |
746 | .num_resources = ARRAY_SIZE(ep93xx_wdt_resources), |
747 | .resource = ep93xx_wdt_resources, |
748 | }; |
749 | |
750 | /************************************************************************* |
751 | * EP93xx IDE |
752 | *************************************************************************/ |
753 | static struct resource ep93xx_ide_resources[] = { |
754 | DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38), |
755 | DEFINE_RES_IRQ(IRQ_EP93XX_EXT3), |
756 | }; |
757 | |
758 | static struct platform_device ep93xx_ide_device = { |
759 | .name = "ep93xx-ide" , |
760 | .id = -1, |
761 | .dev = { |
762 | .dma_mask = &ep93xx_ide_device.dev.coherent_dma_mask, |
763 | .coherent_dma_mask = DMA_BIT_MASK(32), |
764 | }, |
765 | .num_resources = ARRAY_SIZE(ep93xx_ide_resources), |
766 | .resource = ep93xx_ide_resources, |
767 | }; |
768 | |
769 | void __init ep93xx_register_ide(void) |
770 | { |
771 | platform_device_register(&ep93xx_ide_device); |
772 | } |
773 | |
774 | int ep93xx_ide_acquire_gpio(struct platform_device *pdev) |
775 | { |
776 | int err; |
777 | int i; |
778 | |
779 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, label: dev_name(dev: &pdev->dev)); |
780 | if (err) |
781 | return err; |
782 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, label: dev_name(dev: &pdev->dev)); |
783 | if (err) |
784 | goto fail_egpio15; |
785 | for (i = 2; i < 8; i++) { |
786 | err = gpio_request(EP93XX_GPIO_LINE_E(i), label: dev_name(dev: &pdev->dev)); |
787 | if (err) |
788 | goto fail_gpio_e; |
789 | } |
790 | for (i = 4; i < 8; i++) { |
791 | err = gpio_request(EP93XX_GPIO_LINE_G(i), label: dev_name(dev: &pdev->dev)); |
792 | if (err) |
793 | goto fail_gpio_g; |
794 | } |
795 | for (i = 0; i < 8; i++) { |
796 | err = gpio_request(EP93XX_GPIO_LINE_H(i), label: dev_name(dev: &pdev->dev)); |
797 | if (err) |
798 | goto fail_gpio_h; |
799 | } |
800 | |
801 | /* GPIO ports E[7:2], G[7:4] and H used by IDE */ |
802 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE | |
803 | EP93XX_SYSCON_DEVCFG_GONIDE | |
804 | EP93XX_SYSCON_DEVCFG_HONIDE); |
805 | return 0; |
806 | |
807 | fail_gpio_h: |
808 | for (--i; i >= 0; --i) |
809 | gpio_free(EP93XX_GPIO_LINE_H(i)); |
810 | i = 8; |
811 | fail_gpio_g: |
812 | for (--i; i >= 4; --i) |
813 | gpio_free(EP93XX_GPIO_LINE_G(i)); |
814 | i = 8; |
815 | fail_gpio_e: |
816 | for (--i; i >= 2; --i) |
817 | gpio_free(EP93XX_GPIO_LINE_E(i)); |
818 | gpio_free(EP93XX_GPIO_LINE_EGPIO15); |
819 | fail_egpio15: |
820 | gpio_free(EP93XX_GPIO_LINE_EGPIO2); |
821 | return err; |
822 | } |
823 | EXPORT_SYMBOL(ep93xx_ide_acquire_gpio); |
824 | |
825 | void ep93xx_ide_release_gpio(struct platform_device *pdev) |
826 | { |
827 | int i; |
828 | |
829 | for (i = 2; i < 8; i++) |
830 | gpio_free(EP93XX_GPIO_LINE_E(i)); |
831 | for (i = 4; i < 8; i++) |
832 | gpio_free(EP93XX_GPIO_LINE_G(i)); |
833 | for (i = 0; i < 8; i++) |
834 | gpio_free(EP93XX_GPIO_LINE_H(i)); |
835 | gpio_free(EP93XX_GPIO_LINE_EGPIO15); |
836 | gpio_free(EP93XX_GPIO_LINE_EGPIO2); |
837 | |
838 | |
839 | /* GPIO ports E[7:2], G[7:4] and H used by GPIO */ |
840 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE | |
841 | EP93XX_SYSCON_DEVCFG_GONIDE | |
842 | EP93XX_SYSCON_DEVCFG_HONIDE); |
843 | } |
844 | EXPORT_SYMBOL(ep93xx_ide_release_gpio); |
845 | |
846 | /************************************************************************* |
847 | * EP93xx ADC |
848 | *************************************************************************/ |
849 | static struct resource ep93xx_adc_resources[] = { |
850 | DEFINE_RES_MEM(EP93XX_ADC_PHYS_BASE, 0x28), |
851 | DEFINE_RES_IRQ(IRQ_EP93XX_TOUCH), |
852 | }; |
853 | |
854 | static struct platform_device ep93xx_adc_device = { |
855 | .name = "ep93xx-adc" , |
856 | .id = -1, |
857 | .num_resources = ARRAY_SIZE(ep93xx_adc_resources), |
858 | .resource = ep93xx_adc_resources, |
859 | }; |
860 | |
861 | void __init ep93xx_register_adc(void) |
862 | { |
863 | /* Power up ADC, deactivate Touch Screen Controller */ |
864 | ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN, |
865 | EP93XX_SYSCON_DEVCFG_ADCPD); |
866 | |
867 | platform_device_register(&ep93xx_adc_device); |
868 | } |
869 | |
870 | /************************************************************************* |
871 | * EP93xx Security peripheral |
872 | *************************************************************************/ |
873 | |
874 | /* |
875 | * The Maverick Key is 256 bits of micro fuses blown at the factory during |
876 | * manufacturing to uniquely identify a part. |
877 | * |
878 | * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key |
879 | */ |
880 | #define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) |
881 | #define EP93XX_SECURITY_SECFLG EP93XX_SECURITY_REG(0x2400) |
882 | #define EP93XX_SECURITY_FUSEFLG EP93XX_SECURITY_REG(0x2410) |
883 | #define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) |
884 | #define EP93XX_SECURITY_UNIQCHK EP93XX_SECURITY_REG(0x2450) |
885 | #define EP93XX_SECURITY_UNIQVAL EP93XX_SECURITY_REG(0x2460) |
886 | #define EP93XX_SECURITY_SECID1 EP93XX_SECURITY_REG(0x2500) |
887 | #define EP93XX_SECURITY_SECID2 EP93XX_SECURITY_REG(0x2504) |
888 | #define EP93XX_SECURITY_SECCHK1 EP93XX_SECURITY_REG(0x2520) |
889 | #define EP93XX_SECURITY_SECCHK2 EP93XX_SECURITY_REG(0x2524) |
890 | #define EP93XX_SECURITY_UNIQID2 EP93XX_SECURITY_REG(0x2700) |
891 | #define EP93XX_SECURITY_UNIQID3 EP93XX_SECURITY_REG(0x2704) |
892 | #define EP93XX_SECURITY_UNIQID4 EP93XX_SECURITY_REG(0x2708) |
893 | #define EP93XX_SECURITY_UNIQID5 EP93XX_SECURITY_REG(0x270c) |
894 | |
895 | static char ep93xx_soc_id[33]; |
896 | |
897 | static const char __init *ep93xx_get_soc_id(void) |
898 | { |
899 | unsigned int id, id2, id3, id4, id5; |
900 | |
901 | if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1) |
902 | return "bad Hamming code" ; |
903 | |
904 | id = __raw_readl(EP93XX_SECURITY_UNIQID); |
905 | id2 = __raw_readl(EP93XX_SECURITY_UNIQID2); |
906 | id3 = __raw_readl(EP93XX_SECURITY_UNIQID3); |
907 | id4 = __raw_readl(EP93XX_SECURITY_UNIQID4); |
908 | id5 = __raw_readl(EP93XX_SECURITY_UNIQID5); |
909 | |
910 | if (id != id2) |
911 | return "invalid" ; |
912 | |
913 | /* Toss the unique ID into the entropy pool */ |
914 | add_device_randomness(buf: &id2, len: 4); |
915 | add_device_randomness(buf: &id3, len: 4); |
916 | add_device_randomness(buf: &id4, len: 4); |
917 | add_device_randomness(buf: &id5, len: 4); |
918 | |
919 | snprintf(buf: ep93xx_soc_id, size: sizeof(ep93xx_soc_id), |
920 | fmt: "%08x%08x%08x%08x" , id2, id3, id4, id5); |
921 | |
922 | return ep93xx_soc_id; |
923 | } |
924 | |
925 | static const char __init *ep93xx_get_soc_rev(void) |
926 | { |
927 | int rev = ep93xx_chip_revision(); |
928 | |
929 | switch (rev) { |
930 | case EP93XX_CHIP_REV_D0: |
931 | return "D0" ; |
932 | case EP93XX_CHIP_REV_D1: |
933 | return "D1" ; |
934 | case EP93XX_CHIP_REV_E0: |
935 | return "E0" ; |
936 | case EP93XX_CHIP_REV_E1: |
937 | return "E1" ; |
938 | case EP93XX_CHIP_REV_E2: |
939 | return "E2" ; |
940 | default: |
941 | return "unknown" ; |
942 | } |
943 | } |
944 | |
945 | static const char __init *ep93xx_get_machine_name(void) |
946 | { |
947 | return kasprintf(GFP_KERNEL,fmt: "%s" , machine_desc->name); |
948 | } |
949 | |
950 | static struct device __init *ep93xx_init_soc(void) |
951 | { |
952 | struct soc_device_attribute *soc_dev_attr; |
953 | struct soc_device *soc_dev; |
954 | |
955 | soc_dev_attr = kzalloc(size: sizeof(*soc_dev_attr), GFP_KERNEL); |
956 | if (!soc_dev_attr) |
957 | return NULL; |
958 | |
959 | soc_dev_attr->machine = ep93xx_get_machine_name(); |
960 | soc_dev_attr->family = "Cirrus Logic EP93xx" ; |
961 | soc_dev_attr->revision = ep93xx_get_soc_rev(); |
962 | soc_dev_attr->soc_id = ep93xx_get_soc_id(); |
963 | |
964 | soc_dev = soc_device_register(soc_plat_dev_attr: soc_dev_attr); |
965 | if (IS_ERR(ptr: soc_dev)) { |
966 | kfree(objp: soc_dev_attr->machine); |
967 | kfree(objp: soc_dev_attr); |
968 | return NULL; |
969 | } |
970 | |
971 | return soc_device_to_device(soc: soc_dev); |
972 | } |
973 | |
974 | struct device __init *ep93xx_init_devices(void) |
975 | { |
976 | struct device *parent; |
977 | |
978 | /* Disallow access to MaverickCrunch initially */ |
979 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); |
980 | |
981 | /* Default all ports to GPIO */ |
982 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | |
983 | EP93XX_SYSCON_DEVCFG_GONK | |
984 | EP93XX_SYSCON_DEVCFG_EONIDE | |
985 | EP93XX_SYSCON_DEVCFG_GONIDE | |
986 | EP93XX_SYSCON_DEVCFG_HONIDE); |
987 | |
988 | parent = ep93xx_init_soc(); |
989 | |
990 | /* Get the GPIO working early, other devices need it */ |
991 | platform_device_register(&ep93xx_gpio_device); |
992 | |
993 | amba_device_register(&uart1_device, &iomem_resource); |
994 | amba_device_register(&uart2_device, &iomem_resource); |
995 | amba_device_register(&uart3_device, &iomem_resource); |
996 | |
997 | platform_device_register(&ep93xx_rtc_device); |
998 | platform_device_register(&ep93xx_ohci_device); |
999 | platform_device_register(&ep93xx_wdt_device); |
1000 | |
1001 | gpiod_add_lookup_table(table: &ep93xx_leds_gpio_table); |
1002 | gpio_led_register_device(id: -1, pdata: &ep93xx_led_data); |
1003 | |
1004 | return parent; |
1005 | } |
1006 | |
1007 | void ep93xx_restart(enum reboot_mode mode, const char *cmd) |
1008 | { |
1009 | /* |
1010 | * Set then clear the SWRST bit to initiate a software reset |
1011 | */ |
1012 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST); |
1013 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST); |
1014 | |
1015 | while (1) |
1016 | ; |
1017 | } |
1018 | |