palm27x.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Common code for Palm LD, T5, TX, Z72
  4. *
  5. * Copyright (C) 2010-2011 Marek Vasut <[email protected]>
  6. */
  7. #include <linux/platform_device.h>
  8. #include <linux/delay.h>
  9. #include <linux/irq.h>
  10. #include <linux/gpio_keys.h>
  11. #include <linux/input.h>
  12. #include <linux/pda_power.h>
  13. #include <linux/pwm.h>
  14. #include <linux/pwm_backlight.h>
  15. #include <linux/gpio/machine.h>
  16. #include <linux/gpio.h>
  17. #include <linux/wm97xx.h>
  18. #include <linux/power_supply.h>
  19. #include <linux/regulator/max1586.h>
  20. #include <linux/platform_data/i2c-pxa.h>
  21. #include <asm/mach-types.h>
  22. #include <asm/mach/arch.h>
  23. #include <asm/mach/map.h>
  24. #include "pxa27x.h"
  25. #include <linux/platform_data/asoc-pxa.h>
  26. #include <linux/platform_data/mmc-pxamci.h>
  27. #include <linux/platform_data/video-pxafb.h>
  28. #include <linux/platform_data/irda-pxaficp.h>
  29. #include "udc.h"
  30. #include <linux/platform_data/asoc-palm27x.h>
  31. #include "palm27x.h"
  32. #include "generic.h"
  33. #include "devices.h"
  34. /******************************************************************************
  35. * SD/MMC card controller
  36. ******************************************************************************/
  37. #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
  38. static struct pxamci_platform_data palm27x_mci_platform_data = {
  39. .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
  40. .detect_delay_ms = 200,
  41. };
  42. void __init palm27x_mmc_init(struct gpiod_lookup_table *gtable)
  43. {
  44. if (gtable)
  45. gpiod_add_lookup_table(gtable);
  46. pxa_set_mci_info(&palm27x_mci_platform_data);
  47. }
  48. #endif
  49. /******************************************************************************
  50. * Power management - standby
  51. ******************************************************************************/
  52. #if defined(CONFIG_SUSPEND)
  53. void __init palm27x_pm_init(unsigned long str_base)
  54. {
  55. static const unsigned long resume[] = {
  56. 0xe3a00101, /* mov r0, #0x40000000 */
  57. 0xe380060f, /* orr r0, r0, #0x00f00000 */
  58. 0xe590f008, /* ldr pc, [r0, #0x08] */
  59. };
  60. /*
  61. * Copy the bootloader.
  62. * NOTE: PalmZ72 uses a different wakeup method!
  63. */
  64. memcpy(phys_to_virt(str_base), resume, sizeof(resume));
  65. }
  66. #endif
  67. /******************************************************************************
  68. * Framebuffer
  69. ******************************************************************************/
  70. #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
  71. struct pxafb_mode_info palm_320x480_lcd_mode = {
  72. .pixclock = 57692,
  73. .xres = 320,
  74. .yres = 480,
  75. .bpp = 16,
  76. .left_margin = 32,
  77. .right_margin = 1,
  78. .upper_margin = 7,
  79. .lower_margin = 1,
  80. .hsync_len = 4,
  81. .vsync_len = 1,
  82. };
  83. struct pxafb_mode_info palm_320x320_lcd_mode = {
  84. .pixclock = 115384,
  85. .xres = 320,
  86. .yres = 320,
  87. .bpp = 16,
  88. .left_margin = 27,
  89. .right_margin = 7,
  90. .upper_margin = 7,
  91. .lower_margin = 8,
  92. .hsync_len = 6,
  93. .vsync_len = 1,
  94. };
  95. struct pxafb_mode_info palm_320x320_new_lcd_mode = {
  96. .pixclock = 86538,
  97. .xres = 320,
  98. .yres = 320,
  99. .bpp = 16,
  100. .left_margin = 20,
  101. .right_margin = 8,
  102. .upper_margin = 8,
  103. .lower_margin = 5,
  104. .hsync_len = 4,
  105. .vsync_len = 1,
  106. };
  107. static struct pxafb_mach_info palm27x_lcd_screen = {
  108. .num_modes = 1,
  109. .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
  110. };
  111. static int palm27x_lcd_power;
  112. static void palm27x_lcd_ctl(int on, struct fb_var_screeninfo *info)
  113. {
  114. gpio_set_value(palm27x_lcd_power, on);
  115. }
  116. void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode)
  117. {
  118. palm27x_lcd_screen.modes = mode;
  119. if (gpio_is_valid(power)) {
  120. if (!gpio_request(power, "LCD power")) {
  121. pr_err("Palm27x: failed to claim lcd power gpio!\n");
  122. return;
  123. }
  124. if (!gpio_direction_output(power, 1)) {
  125. pr_err("Palm27x: lcd power configuration failed!\n");
  126. return;
  127. }
  128. palm27x_lcd_power = power;
  129. palm27x_lcd_screen.pxafb_lcd_power = palm27x_lcd_ctl;
  130. }
  131. pxa_set_fb_info(NULL, &palm27x_lcd_screen);
  132. }
  133. #endif
  134. /******************************************************************************
  135. * USB Gadget
  136. ******************************************************************************/
  137. #if defined(CONFIG_USB_PXA27X) || \
  138. defined(CONFIG_USB_PXA27X_MODULE)
  139. /* The actual GPIO offsets get filled in in the palm27x_udc_init() call */
  140. static struct gpiod_lookup_table palm27x_udc_gpiod_table = {
  141. .dev_id = "gpio-vbus",
  142. .table = {
  143. GPIO_LOOKUP("gpio-pxa", 0,
  144. "vbus", GPIO_ACTIVE_HIGH),
  145. GPIO_LOOKUP("gpio-pxa", 0,
  146. "pullup", GPIO_ACTIVE_HIGH),
  147. { },
  148. },
  149. };
  150. static struct platform_device palm27x_gpio_vbus = {
  151. .name = "gpio-vbus",
  152. .id = -1,
  153. };
  154. void __init palm27x_udc_init(int vbus, int pullup, int vbus_inverted)
  155. {
  156. palm27x_udc_gpiod_table.table[0].chip_hwnum = vbus;
  157. palm27x_udc_gpiod_table.table[1].chip_hwnum = pullup;
  158. if (vbus_inverted)
  159. palm27x_udc_gpiod_table.table[0].flags = GPIO_ACTIVE_LOW;
  160. gpiod_add_lookup_table(&palm27x_udc_gpiod_table);
  161. platform_device_register(&palm27x_gpio_vbus);
  162. }
  163. #endif
  164. /******************************************************************************
  165. * IrDA
  166. ******************************************************************************/
  167. #if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
  168. static struct pxaficp_platform_data palm27x_ficp_platform_data = {
  169. .transceiver_cap = IR_SIRMODE | IR_OFF,
  170. };
  171. void __init palm27x_irda_init(int pwdn)
  172. {
  173. palm27x_ficp_platform_data.gpio_pwdown = pwdn;
  174. pxa_set_ficp_info(&palm27x_ficp_platform_data);
  175. }
  176. #endif
  177. /******************************************************************************
  178. * WM97xx audio, battery
  179. ******************************************************************************/
  180. #if defined(CONFIG_TOUCHSCREEN_WM97XX) || \
  181. defined(CONFIG_TOUCHSCREEN_WM97XX_MODULE)
  182. static struct wm97xx_batt_pdata palm27x_batt_pdata = {
  183. .batt_aux = WM97XX_AUX_ID3,
  184. .temp_aux = WM97XX_AUX_ID2,
  185. .batt_mult = 1000,
  186. .batt_div = 414,
  187. .temp_mult = 1,
  188. .temp_div = 1,
  189. .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO,
  190. .batt_name = "main-batt",
  191. };
  192. static struct wm97xx_pdata palm27x_wm97xx_pdata = {
  193. .batt_pdata = &palm27x_batt_pdata,
  194. };
  195. static pxa2xx_audio_ops_t palm27x_ac97_pdata = {
  196. .codec_pdata = { &palm27x_wm97xx_pdata, },
  197. };
  198. static struct palm27x_asoc_info palm27x_asoc_pdata = {
  199. .jack_gpio = -1,
  200. };
  201. static struct platform_device palm27x_asoc = {
  202. .name = "palm27x-asoc",
  203. .id = -1,
  204. .dev = {
  205. .platform_data = &palm27x_asoc_pdata,
  206. },
  207. };
  208. void __init palm27x_ac97_init(int minv, int maxv, int jack, int reset)
  209. {
  210. palm27x_ac97_pdata.reset_gpio = reset;
  211. palm27x_asoc_pdata.jack_gpio = jack;
  212. if (minv < 0 || maxv < 0) {
  213. palm27x_ac97_pdata.codec_pdata[0] = NULL;
  214. pxa_set_ac97_info(&palm27x_ac97_pdata);
  215. } else {
  216. palm27x_batt_pdata.min_voltage = minv,
  217. palm27x_batt_pdata.max_voltage = maxv,
  218. pxa_set_ac97_info(&palm27x_ac97_pdata);
  219. platform_device_register(&palm27x_asoc);
  220. }
  221. }
  222. #endif
  223. /******************************************************************************
  224. * Backlight
  225. ******************************************************************************/
  226. #if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
  227. static struct pwm_lookup palm27x_pwm_lookup[] = {
  228. PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight.0", NULL, 3500 * 1024,
  229. PWM_POLARITY_NORMAL),
  230. };
  231. static int palm_bl_power;
  232. static int palm_lcd_power;
  233. static int palm27x_backlight_init(struct device *dev)
  234. {
  235. int ret;
  236. ret = gpio_request(palm_bl_power, "BL POWER");
  237. if (ret)
  238. goto err;
  239. ret = gpio_direction_output(palm_bl_power, 0);
  240. if (ret)
  241. goto err2;
  242. if (gpio_is_valid(palm_lcd_power)) {
  243. ret = gpio_request(palm_lcd_power, "LCD POWER");
  244. if (ret)
  245. goto err2;
  246. ret = gpio_direction_output(palm_lcd_power, 0);
  247. if (ret)
  248. goto err3;
  249. }
  250. return 0;
  251. err3:
  252. gpio_free(palm_lcd_power);
  253. err2:
  254. gpio_free(palm_bl_power);
  255. err:
  256. return ret;
  257. }
  258. static int palm27x_backlight_notify(struct device *dev, int brightness)
  259. {
  260. gpio_set_value(palm_bl_power, brightness);
  261. if (gpio_is_valid(palm_lcd_power))
  262. gpio_set_value(palm_lcd_power, brightness);
  263. return brightness;
  264. }
  265. static void palm27x_backlight_exit(struct device *dev)
  266. {
  267. gpio_free(palm_bl_power);
  268. if (gpio_is_valid(palm_lcd_power))
  269. gpio_free(palm_lcd_power);
  270. }
  271. static struct platform_pwm_backlight_data palm27x_backlight_data = {
  272. .max_brightness = 0xfe,
  273. .dft_brightness = 0x7e,
  274. .init = palm27x_backlight_init,
  275. .notify = palm27x_backlight_notify,
  276. .exit = palm27x_backlight_exit,
  277. };
  278. static struct platform_device palm27x_backlight = {
  279. .name = "pwm-backlight",
  280. .dev = {
  281. .parent = &pxa27x_device_pwm0.dev,
  282. .platform_data = &palm27x_backlight_data,
  283. },
  284. };
  285. void __init palm27x_pwm_init(int bl, int lcd)
  286. {
  287. palm_bl_power = bl;
  288. palm_lcd_power = lcd;
  289. pwm_add_table(palm27x_pwm_lookup, ARRAY_SIZE(palm27x_pwm_lookup));
  290. platform_device_register(&palm27x_backlight);
  291. }
  292. #endif
  293. /******************************************************************************
  294. * Power supply
  295. ******************************************************************************/
  296. #if defined(CONFIG_PDA_POWER) || defined(CONFIG_PDA_POWER_MODULE)
  297. static int palm_ac_state;
  298. static int palm_usb_state;
  299. static int palm27x_power_supply_init(struct device *dev)
  300. {
  301. int ret;
  302. ret = gpio_request(palm_ac_state, "AC state");
  303. if (ret)
  304. goto err1;
  305. ret = gpio_direction_input(palm_ac_state);
  306. if (ret)
  307. goto err2;
  308. if (gpio_is_valid(palm_usb_state)) {
  309. ret = gpio_request(palm_usb_state, "USB state");
  310. if (ret)
  311. goto err2;
  312. ret = gpio_direction_input(palm_usb_state);
  313. if (ret)
  314. goto err3;
  315. }
  316. return 0;
  317. err3:
  318. gpio_free(palm_usb_state);
  319. err2:
  320. gpio_free(palm_ac_state);
  321. err1:
  322. return ret;
  323. }
  324. static void palm27x_power_supply_exit(struct device *dev)
  325. {
  326. gpio_free(palm_usb_state);
  327. gpio_free(palm_ac_state);
  328. }
  329. static int palm27x_is_ac_online(void)
  330. {
  331. return gpio_get_value(palm_ac_state);
  332. }
  333. static int palm27x_is_usb_online(void)
  334. {
  335. return !gpio_get_value(palm_usb_state);
  336. }
  337. static char *palm27x_supplicants[] = {
  338. "main-battery",
  339. };
  340. static struct pda_power_pdata palm27x_ps_info = {
  341. .init = palm27x_power_supply_init,
  342. .exit = palm27x_power_supply_exit,
  343. .is_ac_online = palm27x_is_ac_online,
  344. .is_usb_online = palm27x_is_usb_online,
  345. .supplied_to = palm27x_supplicants,
  346. .num_supplicants = ARRAY_SIZE(palm27x_supplicants),
  347. };
  348. static struct platform_device palm27x_power_supply = {
  349. .name = "pda-power",
  350. .id = -1,
  351. .dev = {
  352. .platform_data = &palm27x_ps_info,
  353. },
  354. };
  355. void __init palm27x_power_init(int ac, int usb)
  356. {
  357. palm_ac_state = ac;
  358. palm_usb_state = usb;
  359. platform_device_register(&palm27x_power_supply);
  360. }
  361. #endif
  362. /******************************************************************************
  363. * Core power regulator
  364. ******************************************************************************/
  365. #if defined(CONFIG_REGULATOR_MAX1586) || \
  366. defined(CONFIG_REGULATOR_MAX1586_MODULE)
  367. static struct regulator_consumer_supply palm27x_max1587a_consumers[] = {
  368. REGULATOR_SUPPLY("vcc_core", NULL),
  369. };
  370. static struct regulator_init_data palm27x_max1587a_v3_info = {
  371. .constraints = {
  372. .name = "vcc_core range",
  373. .min_uV = 900000,
  374. .max_uV = 1705000,
  375. .always_on = 1,
  376. .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
  377. },
  378. .consumer_supplies = palm27x_max1587a_consumers,
  379. .num_consumer_supplies = ARRAY_SIZE(palm27x_max1587a_consumers),
  380. };
  381. static struct max1586_subdev_data palm27x_max1587a_subdevs[] = {
  382. {
  383. .name = "vcc_core",
  384. .id = MAX1586_V3,
  385. .platform_data = &palm27x_max1587a_v3_info,
  386. }
  387. };
  388. static struct max1586_platform_data palm27x_max1587a_info = {
  389. .subdevs = palm27x_max1587a_subdevs,
  390. .num_subdevs = ARRAY_SIZE(palm27x_max1587a_subdevs),
  391. .v3_gain = MAX1586_GAIN_R24_3k32, /* 730..1550 mV */
  392. };
  393. static struct i2c_board_info __initdata palm27x_pi2c_board_info[] = {
  394. {
  395. I2C_BOARD_INFO("max1586", 0x14),
  396. .platform_data = &palm27x_max1587a_info,
  397. },
  398. };
  399. static struct i2c_pxa_platform_data palm27x_i2c_power_info = {
  400. .use_pio = 1,
  401. };
  402. void __init palm27x_pmic_init(void)
  403. {
  404. i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info));
  405. pxa27x_set_i2c_power_info(&palm27x_i2c_power_info);
  406. }
  407. #endif