1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * arch/arm/mach-ep93xx/vision_ep9307.c |
4 | * Vision Engraving Systems EP9307 SoM support. |
5 | * |
6 | * Copyright (C) 2008-2011 Vision Engraving Systems |
7 | * H Hartley Sweeten <hsweeten@visionengravers.com> |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | |
12 | #include <linux/kernel.h> |
13 | #include <linux/init.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/irq.h> |
16 | #include <linux/gpio.h> |
17 | #include <linux/gpio/machine.h> |
18 | #include <linux/fb.h> |
19 | #include <linux/io.h> |
20 | #include <linux/mtd/partitions.h> |
21 | #include <linux/i2c.h> |
22 | #include <linux/platform_data/pca953x.h> |
23 | #include <linux/spi/spi.h> |
24 | #include <linux/spi/flash.h> |
25 | #include <linux/spi/mmc_spi.h> |
26 | #include <linux/mmc/host.h> |
27 | |
28 | #include <sound/cs4271.h> |
29 | |
30 | #include "hardware.h" |
31 | #include <linux/platform_data/video-ep93xx.h> |
32 | #include <linux/platform_data/spi-ep93xx.h> |
33 | #include "gpio-ep93xx.h" |
34 | |
35 | #include <asm/mach-types.h> |
36 | #include <asm/mach/map.h> |
37 | #include <asm/mach/arch.h> |
38 | |
39 | #include "soc.h" |
40 | |
41 | /************************************************************************* |
42 | * Static I/O mappings for the FPGA |
43 | *************************************************************************/ |
44 | #define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE |
45 | #define VISION_VIRT_BASE 0xfebff000 |
46 | |
47 | static struct map_desc vision_io_desc[] __initdata = { |
48 | { |
49 | .virtual = VISION_VIRT_BASE, |
50 | .pfn = __phys_to_pfn(VISION_PHYS_BASE), |
51 | .length = SZ_4K, |
52 | .type = MT_DEVICE, |
53 | }, |
54 | }; |
55 | |
56 | static void __init vision_map_io(void) |
57 | { |
58 | ep93xx_map_io(); |
59 | |
60 | iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc)); |
61 | } |
62 | |
63 | /************************************************************************* |
64 | * Ethernet |
65 | *************************************************************************/ |
66 | static struct ep93xx_eth_data vision_eth_data __initdata = { |
67 | .phy_id = 1, |
68 | }; |
69 | |
70 | /************************************************************************* |
71 | * Framebuffer |
72 | *************************************************************************/ |
73 | #define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1 |
74 | |
75 | static int vision_lcd_setup(struct platform_device *pdev) |
76 | { |
77 | int err; |
78 | |
79 | err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH, |
80 | label: dev_name(dev: &pdev->dev)); |
81 | if (err) |
82 | return err; |
83 | |
84 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS | |
85 | EP93XX_SYSCON_DEVCFG_RASONP3 | |
86 | EP93XX_SYSCON_DEVCFG_EXVC); |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | static void vision_lcd_teardown(struct platform_device *pdev) |
92 | { |
93 | gpio_free(VISION_LCD_ENABLE); |
94 | } |
95 | |
96 | static void vision_lcd_blank(int blank_mode, struct fb_info *info) |
97 | { |
98 | if (blank_mode) |
99 | gpio_set_value(VISION_LCD_ENABLE, value: 0); |
100 | else |
101 | gpio_set_value(VISION_LCD_ENABLE, value: 1); |
102 | } |
103 | |
104 | static struct ep93xxfb_mach_info ep93xxfb_info __initdata = { |
105 | .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, |
106 | .setup = vision_lcd_setup, |
107 | .teardown = vision_lcd_teardown, |
108 | .blank = vision_lcd_blank, |
109 | }; |
110 | |
111 | |
112 | /************************************************************************* |
113 | * GPIO Expanders |
114 | *************************************************************************/ |
115 | #define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1) |
116 | #define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16) |
117 | #define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16) |
118 | #define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16) |
119 | |
120 | static struct pca953x_platform_data pca953x_74_gpio_data = { |
121 | .gpio_base = PCA9539_74_GPIO_BASE, |
122 | .irq_base = EP93XX_BOARD_IRQ(0), |
123 | }; |
124 | |
125 | static struct pca953x_platform_data pca953x_75_gpio_data = { |
126 | .gpio_base = PCA9539_75_GPIO_BASE, |
127 | .irq_base = -1, |
128 | }; |
129 | |
130 | static struct pca953x_platform_data pca953x_76_gpio_data = { |
131 | .gpio_base = PCA9539_76_GPIO_BASE, |
132 | .irq_base = -1, |
133 | }; |
134 | |
135 | static struct pca953x_platform_data pca953x_77_gpio_data = { |
136 | .gpio_base = PCA9539_77_GPIO_BASE, |
137 | .irq_base = -1, |
138 | }; |
139 | |
140 | /************************************************************************* |
141 | * I2C Bus |
142 | *************************************************************************/ |
143 | |
144 | static struct i2c_board_info vision_i2c_info[] __initdata = { |
145 | { |
146 | I2C_BOARD_INFO("isl1208" , 0x6f), |
147 | .irq = IRQ_EP93XX_EXT1, |
148 | }, { |
149 | I2C_BOARD_INFO("pca9539" , 0x74), |
150 | .platform_data = &pca953x_74_gpio_data, |
151 | }, { |
152 | I2C_BOARD_INFO("pca9539" , 0x75), |
153 | .platform_data = &pca953x_75_gpio_data, |
154 | }, { |
155 | I2C_BOARD_INFO("pca9539" , 0x76), |
156 | .platform_data = &pca953x_76_gpio_data, |
157 | }, { |
158 | I2C_BOARD_INFO("pca9539" , 0x77), |
159 | .platform_data = &pca953x_77_gpio_data, |
160 | }, |
161 | }; |
162 | |
163 | /************************************************************************* |
164 | * SPI CS4271 Audio Codec |
165 | *************************************************************************/ |
166 | static struct cs4271_platform_data vision_cs4271_data = { |
167 | .gpio_nreset = EP93XX_GPIO_LINE_H(2), |
168 | }; |
169 | |
170 | /************************************************************************* |
171 | * SPI Flash |
172 | *************************************************************************/ |
173 | static struct mtd_partition vision_spi_flash_partitions[] = { |
174 | { |
175 | .name = "SPI bootstrap" , |
176 | .offset = 0, |
177 | .size = SZ_4K, |
178 | }, { |
179 | .name = "Bootstrap config" , |
180 | .offset = MTDPART_OFS_APPEND, |
181 | .size = SZ_4K, |
182 | }, { |
183 | .name = "System config" , |
184 | .offset = MTDPART_OFS_APPEND, |
185 | .size = MTDPART_SIZ_FULL, |
186 | }, |
187 | }; |
188 | |
189 | static struct flash_platform_data vision_spi_flash_data = { |
190 | .name = "SPI Flash" , |
191 | .parts = vision_spi_flash_partitions, |
192 | .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions), |
193 | }; |
194 | |
195 | /************************************************************************* |
196 | * SPI SD/MMC host |
197 | *************************************************************************/ |
198 | static struct mmc_spi_platform_data vision_spi_mmc_data = { |
199 | .detect_delay = 100, |
200 | .powerup_msecs = 100, |
201 | .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, |
202 | .caps2 = MMC_CAP2_RO_ACTIVE_HIGH, |
203 | }; |
204 | |
205 | static struct gpiod_lookup_table vision_spi_mmc_gpio_table = { |
206 | .dev_id = "mmc_spi.2" , /* "mmc_spi @ CS2 */ |
207 | .table = { |
208 | /* Card detect */ |
209 | GPIO_LOOKUP_IDX("B" , 7, NULL, 0, GPIO_ACTIVE_LOW), |
210 | /* Write protect */ |
211 | GPIO_LOOKUP_IDX("F" , 0, NULL, 1, GPIO_ACTIVE_HIGH), |
212 | { }, |
213 | }, |
214 | }; |
215 | |
216 | /************************************************************************* |
217 | * SPI Bus |
218 | *************************************************************************/ |
219 | static struct spi_board_info vision_spi_board_info[] __initdata = { |
220 | { |
221 | .modalias = "cs4271" , |
222 | .platform_data = &vision_cs4271_data, |
223 | .max_speed_hz = 6000000, |
224 | .bus_num = 0, |
225 | .chip_select = 0, |
226 | .mode = SPI_MODE_3, |
227 | }, { |
228 | .modalias = "sst25l" , |
229 | .platform_data = &vision_spi_flash_data, |
230 | .max_speed_hz = 20000000, |
231 | .bus_num = 0, |
232 | .chip_select = 1, |
233 | .mode = SPI_MODE_3, |
234 | }, { |
235 | .modalias = "mmc_spi" , |
236 | .platform_data = &vision_spi_mmc_data, |
237 | .max_speed_hz = 20000000, |
238 | .bus_num = 0, |
239 | .chip_select = 2, |
240 | .mode = SPI_MODE_3, |
241 | }, |
242 | }; |
243 | |
244 | static struct gpiod_lookup_table vision_spi_cs_gpio_table = { |
245 | .dev_id = "spi0" , |
246 | .table = { |
247 | GPIO_LOOKUP_IDX("A" , 6, "cs" , 0, GPIO_ACTIVE_LOW), |
248 | GPIO_LOOKUP_IDX("A" , 7, "cs" , 1, GPIO_ACTIVE_LOW), |
249 | GPIO_LOOKUP_IDX("G" , 2, "cs" , 2, GPIO_ACTIVE_LOW), |
250 | { }, |
251 | }, |
252 | }; |
253 | |
254 | static struct ep93xx_spi_info vision_spi_master __initdata = { |
255 | .use_dma = 1, |
256 | }; |
257 | |
258 | /************************************************************************* |
259 | * I2S Audio |
260 | *************************************************************************/ |
261 | static struct platform_device vision_audio_device = { |
262 | .name = "edb93xx-audio" , |
263 | .id = -1, |
264 | }; |
265 | |
266 | static void __init vision_register_i2s(void) |
267 | { |
268 | ep93xx_register_i2s(); |
269 | platform_device_register(&vision_audio_device); |
270 | } |
271 | |
272 | /************************************************************************* |
273 | * Machine Initialization |
274 | *************************************************************************/ |
275 | static void __init vision_init_machine(void) |
276 | { |
277 | ep93xx_init_devices(); |
278 | ep93xx_register_flash(width: 2, EP93XX_CS6_PHYS_BASE, SZ_64M); |
279 | ep93xx_register_eth(data: &vision_eth_data, copy_addr: 1); |
280 | ep93xx_register_fb(data: &ep93xxfb_info); |
281 | ep93xx_register_pwm(pwm0: 1, pwm1: 0); |
282 | |
283 | /* |
284 | * Request the gpio expander's interrupt gpio line now to prevent |
285 | * the kernel from doing a WARN in gpiolib:gpio_ensure_requested(). |
286 | */ |
287 | if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN, |
288 | label: "pca9539:74" )) |
289 | pr_warn("cannot request interrupt gpio for pca9539:74\n" ); |
290 | |
291 | vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)); |
292 | |
293 | ep93xx_register_i2c(devices: vision_i2c_info, |
294 | ARRAY_SIZE(vision_i2c_info)); |
295 | gpiod_add_lookup_table(table: &vision_spi_mmc_gpio_table); |
296 | gpiod_add_lookup_table(table: &vision_spi_cs_gpio_table); |
297 | ep93xx_register_spi(info: &vision_spi_master, devices: vision_spi_board_info, |
298 | ARRAY_SIZE(vision_spi_board_info)); |
299 | vision_register_i2s(); |
300 | } |
301 | |
302 | MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307" ) |
303 | /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */ |
304 | .atag_offset = 0x100, |
305 | .nr_irqs = NR_EP93XX_IRQS + EP93XX_BOARD_IRQS, |
306 | .map_io = vision_map_io, |
307 | .init_irq = ep93xx_init_irq, |
308 | .init_time = ep93xx_timer_init, |
309 | .init_machine = vision_init_machine, |
310 | .restart = ep93xx_restart, |
311 | MACHINE_END |
312 | |