^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/arm/mach-pxa/colibri-pxa3xx.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Common functions for all Toradex PXA3xx modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Daniel Mack <daniel@caiaq.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/mach-types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/system_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/mach/arch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/mach/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <mach/pxa3xx-regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "mfp-pxa300.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "colibri.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/platform_data/mmc-pxamci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/platform_data/video-pxafb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/platform_data/mtd-nand-pxa3xx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "generic.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "devices.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #if defined(CONFIG_AX88796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ETHER_ADDR_LEN 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static u8 ether_mac_addr[ETHER_ADDR_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) void __init colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u64 serial = ((u64) system_serial_high << 32) | system_serial_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * If the bootloader passed in a serial boot tag, which contains a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * valid ethernet MAC, pass it to the interface. Toradex ships the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * modules with their own bootloader which provides a valid MAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * this way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) for (i = 0; i < ETHER_ADDR_LEN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ether_mac_addr[i] = serial & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) serial >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (is_valid_ether_addr(ether_mac_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) plat_data->flags |= AXFLG_MAC_FROMPLATFORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) plat_data->mac_addr = ether_mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) printk(KERN_INFO "%s(): taking MAC from serial boot tag\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) plat_data->flags |= AXFLG_MAC_FROMDEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) printk(KERN_INFO "%s(): no valid serial boot tag found, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "taking MAC from device\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int lcd_bl_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * LCD panel (Sharp LQ043T3DX02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void colibri_lcd_backlight(int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) gpio_set_value(lcd_bl_pin, !!on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static struct pxafb_mode_info sharp_lq43_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .pixclock = 101936,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .xres = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .yres = 272,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .bpp = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .depth = 18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .hsync_len = 41,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .left_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .right_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .vsync_len = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .upper_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .lower_margin = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .sync = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .cmap_greyscale = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static struct pxafb_mach_info sharp_lq43_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .modes = &sharp_lq43_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .num_modes = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .cmap_inverse = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .cmap_static = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .lcd_conn = LCD_COLOR_TFT_18BPP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .pxafb_backlight_power = colibri_lcd_backlight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void __init colibri_pxa3xx_init_lcd(int bl_pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) lcd_bl_pin = bl_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) gpio_request(bl_pin, "lcd backlight");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) gpio_direction_output(bl_pin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pxa_set_fb_info(NULL, &sharp_lq43_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static struct mtd_partition colibri_nand_partitions[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .name = "bootloader",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .offset = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .size = SZ_512K,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .mask_flags = MTD_WRITEABLE, /* force read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .name = "kernel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .offset = MTDPART_OFS_APPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .size = SZ_4M,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .mask_flags = MTD_WRITEABLE, /* force read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .name = "reserved",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .offset = MTDPART_OFS_APPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .size = SZ_1M,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .mask_flags = MTD_WRITEABLE, /* force read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .name = "fs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .offset = MTDPART_OFS_APPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .size = MTDPART_SIZ_FULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct pxa3xx_nand_platform_data colibri_nand_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .keep_config = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .parts = colibri_nand_partitions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .nr_parts = ARRAY_SIZE(colibri_nand_partitions),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) void __init colibri_pxa3xx_init_nand(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pxa3xx_set_nand_info(&colibri_nand_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)