123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
- * (http://www.friendlyarm.com)
- */
- #include <config.h>
- #include <common.h>
- #include <command.h>
- #include <fdt_support.h>
- #include <log.h>
- #ifdef CONFIG_PWM_NX
- #include <pwm.h>
- #endif
- #include <asm/io.h>
- #include <asm/arch/nexell.h>
- #include <asm/arch/nx_gpio.h>
- #include <asm/arch/display.h>
- #include <asm/arch/display_dev.h>
- #include <u-boot/md5.h>
- #include <linux/stringify.h>
- #include "hwrev.h"
- #include "onewire.h"
- #include "nxp-fb.h"
- #include <env_internal.h> /* for env_save() */
- #include <asm/mach-types.h>
- DECLARE_GLOBAL_DATA_PTR;
- enum gpio_group {
- gpio_a, gpio_b, gpio_c, gpio_d, gpio_e,
- };
- #ifdef CONFIG_PWM_NX
- struct pwm_device {
- int grp;
- int bit;
- int io_fn;
- };
- static inline void bd_pwm_config_gpio(int ch)
- {
- struct pwm_device pwm_dev[] = {
- [0] = { .grp = gpio_d, .bit = 1, .io_fn = 0 },
- [1] = { .grp = gpio_c, .bit = 13, .io_fn = 1 },
- [2] = { .grp = gpio_c, .bit = 14, .io_fn = 1 },
- [3] = { .grp = gpio_d, .bit = 0, .io_fn = 0 },
- };
- int gp = pwm_dev[ch].grp;
- int io = pwm_dev[ch].bit;
- /* pwm backlight OFF: HIGH, ON: LOW */
- nx_gpio_set_pad_function(gp, io, pwm_dev[ch].io_fn);
- nx_gpio_set_output_value(gp, io, 1);
- nx_gpio_set_output_enable(gp, io, 1);
- }
- #endif
- static void bd_backlight_off(void)
- {
- #ifdef CONFIG_S5P4418_ONEWIRE
- onewire_set_backlight(0);
- #elif defined(BACKLIGHT_CH)
- bd_pwm_config_gpio(BACKLIGHT_CH);
- #endif
- }
- static void bd_backlight_on(void)
- {
- #ifdef CONFIG_S5P4418_ONEWIRE
- onewire_set_backlight(127);
- #elif defined(BACKLIGHT_CH)
- /* pwm backlight ON: HIGH, ON: LOW */
- pwm_init(BACKLIGHT_CH,
- BACKLIGHT_DIV, BACKLIGHT_INV);
- pwm_config(BACKLIGHT_CH,
- TO_DUTY_NS(BACKLIGHT_DUTY, BACKLIGHT_HZ),
- TO_PERIOD_NS(BACKLIGHT_HZ));
- #endif
- }
- static void bd_lcd_config_gpio(void)
- {
- int i;
- for (i = 0; i < 28; i++) {
- nx_gpio_set_pad_function(gpio_a, i, 1);
- nx_gpio_set_drive_strength(gpio_a, i, 0);
- nx_gpio_set_pull_mode(gpio_a, i, 2);
- }
- nx_gpio_set_drive_strength(gpio_a, 0, 1);
- }
- /* DEFAULT mmc dev for eMMC boot (dwmmc.2) */
- static int mmc_boot_dev;
- int board_mmc_bootdev(void)
- {
- return mmc_boot_dev;
- }
- /* call from common/env_mmc.c */
- int mmc_get_env_dev(void)
- {
- return mmc_boot_dev;
- }
- #ifdef CONFIG_DISPLAY_BOARDINFO
- int checkboard(void)
- {
- printf("Board: %s\n", get_board_name());
- return 0;
- }
- #endif
- int nx_display_fixup_dp(struct nx_display_dev *dp)
- {
- struct nxp_lcd *lcd = bd_get_lcd();
- enum lcd_format fmt = bd_get_lcd_format();
- struct nxp_lcd_timing *timing = &lcd->timing;
- struct dp_sync_info *sync = &dp->sync;
- struct dp_plane_info *plane = &dp->planes[0];
- int i;
- u32 clk = 800000000;
- u32 div;
- sync->h_active_len = lcd->width;
- sync->h_sync_width = timing->h_sw;
- sync->h_back_porch = timing->h_bp;
- sync->h_front_porch = timing->h_fp;
- sync->h_sync_invert = !lcd->polarity.inv_hsync;
- sync->v_active_len = lcd->height;
- sync->v_sync_width = timing->v_sw;
- sync->v_back_porch = timing->v_bp;
- sync->v_front_porch = timing->v_fp;
- sync->v_sync_invert = !lcd->polarity.inv_vsync;
- /* calculates pixel clock */
- div = timing->h_sw + timing->h_bp + timing->h_fp + lcd->width;
- div *= timing->v_sw + timing->v_bp + timing->v_fp + lcd->height;
- div *= lcd->freq ? : 60;
- clk /= div;
- dp->ctrl.clk_div_lv0 = clk;
- dp->ctrl.clk_inv_lv0 = lcd->polarity.rise_vclk;
- dp->top.screen_width = lcd->width;
- dp->top.screen_height = lcd->height;
- for (i = 0; i < dp->top.plane_num; i++, plane++) {
- if (plane->enable) {
- plane->width = lcd->width;
- plane->height = lcd->height;
- }
- }
- /* initialize display device type */
- if (fmt == LCD_RGB) {
- dp->dev_type = DP_DEVICE_RGBLCD;
- } else if (fmt == LCD_HDMI) {
- struct dp_hdmi_dev *dev = (struct dp_hdmi_dev *)dp->device;
- dp->dev_type = DP_DEVICE_HDMI;
- if (lcd->width == 1920 && lcd->height == 1080)
- dev->preset = 1;
- else
- dev->preset = 0;
- } else {
- struct dp_lvds_dev *dev = (struct dp_lvds_dev *)dp->device;
- dp->dev_type = DP_DEVICE_LVDS;
- dev->lvds_format = (fmt & 0x3);
- }
- return 0;
- }
- /* --------------------------------------------------------------------------
- * initialize board status.
- */
- #define MMC_BOOT_CH0 (0)
- #define MMC_BOOT_CH1 (1 << 3)
- #define MMC_BOOT_CH2 (1 << 19)
- static void bd_bootdev_init(void)
- {
- unsigned int rst = readl(PHY_BASEADDR_CLKPWR + SYSRSTCONFIG);
- rst &= (1 << 19) | (1 << 3);
- if (rst == MMC_BOOT_CH0) {
- /* mmc dev 1 for SD boot */
- mmc_boot_dev = 1;
- }
- }
- #ifdef CONFIG_S5P4418_ONEWIRE
- static void bd_onewire_init(void)
- {
- unsigned char lcd;
- unsigned short fw_ver;
- onewire_init();
- onewire_get_info(&lcd, &fw_ver);
- }
- #endif
- static void bd_lcd_init(void)
- {
- struct nxp_lcd *cfg;
- int id = -1;
- int ret;
- #ifdef CONFIG_S5P4418_ONEWIRE
- id = onewire_get_lcd_id();
- /* -1: onwire probe failed
- * 0: bad
- * >0: identified
- */
- #endif
- ret = bd_setup_lcd_by_id(id);
- if (id <= 0 || ret != id) {
- printf("Panel: N/A (%d)\n", id);
- bd_setup_lcd_by_name("HDMI720P60");
- } else {
- printf("Panel: %s\n", bd_get_lcd_name());
- cfg = bd_get_lcd();
- if (cfg->gpio_init)
- cfg->gpio_init();
- }
- }
- static int mac_read_from_generic_eeprom(u8 *addr)
- {
- return -1;
- }
- static void make_ether_addr(u8 *addr)
- {
- u32 hash[20];
- #define ETHER_MAC_TAG "ethmac"
- memset(hash, 0, sizeof(hash));
- memcpy(hash + 12, ETHER_MAC_TAG, sizeof(ETHER_MAC_TAG));
- hash[4] = readl(PHY_BASEADDR_ECID + 0x00);
- hash[5] = readl(PHY_BASEADDR_ECID + 0x04);
- hash[6] = readl(PHY_BASEADDR_ECID + 0x08);
- hash[7] = readl(PHY_BASEADDR_ECID + 0x0c);
- md5((unsigned char *)&hash[4], 64, (unsigned char *)hash);
- hash[0] ^= hash[2];
- hash[1] ^= hash[3];
- memcpy(addr, (char *)hash, 6);
- addr[0] &= 0xfe; /* clear multicast bit */
- addr[0] |= 0x02;
- }
- static void set_ether_addr(void)
- {
- unsigned char mac[6];
- char ethaddr[20];
- int ret;
- if (env_get("ethaddr"))
- return;
- ret = mac_read_from_generic_eeprom(mac);
- if (ret < 0)
- make_ether_addr(mac);
- sprintf(ethaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
- if (!ret)
- printf("MAC: [%s]\n", ethaddr);
- env_set("ethaddr", ethaddr);
- }
- #ifdef CONFIG_REVISION_TAG
- static void set_board_rev(void)
- {
- char info[64] = {0, };
- snprintf(info, ARRAY_SIZE(info), "%02x", get_board_rev());
- env_set("board_rev", info);
- }
- #endif
- static void set_dtb_name(void)
- {
- char info[64] = {0, };
- snprintf(info, ARRAY_SIZE(info),
- "s5p4418-nanopi2-rev%02x.dtb", get_board_rev());
- env_set("dtb_name", info);
- }
- static void bd_update_env(void)
- {
- char *lcdtype = env_get("lcdtype");
- char *lcddpi = env_get("lcddpi");
- char *bootargs = env_get("bootargs");
- const char *name;
- char *p = NULL;
- int rootdev = board_mmc_bootdev();
- int need_save = 0;
- #define CMDLINE_LCD " lcd="
- char cmdline[CONFIG_SYS_CBSIZE];
- int n = 1;
- if (rootdev != CONFIG_ROOT_DEV && !env_get("firstboot")) {
- env_set_ulong("rootdev", rootdev);
- env_set("firstboot", "0");
- need_save = 1;
- }
- if (lcdtype) {
- /* Setup again as user specified LCD in env */
- bd_setup_lcd_by_name(lcdtype);
- }
- name = bd_get_lcd_name();
- if (bootargs)
- n = strlen(bootargs); /* isn't 0 for NULL */
- else
- cmdline[0] = '\0';
- if ((n + strlen(name) + sizeof(CMDLINE_LCD)) > sizeof(cmdline)) {
- printf("Error: `bootargs' is too large (%d)\n", n);
- goto __exit;
- }
- if (bootargs) {
- p = strstr(bootargs, CMDLINE_LCD);
- if (p) {
- n = (p - bootargs);
- p += strlen(CMDLINE_LCD);
- }
- strncpy(cmdline, bootargs, n);
- }
- /* add `lcd=NAME,NUMdpi' */
- strncpy(cmdline + n, CMDLINE_LCD, strlen(CMDLINE_LCD));
- n += strlen(CMDLINE_LCD);
- strcpy(cmdline + n, name);
- n += strlen(name);
- if (lcddpi) {
- n += sprintf(cmdline + n, ",%sdpi", lcddpi);
- } else {
- int dpi = bd_get_lcd_density();
- if (dpi > 0 && dpi < 600)
- n += sprintf(cmdline + n, ",%ddpi", dpi);
- }
- /* copy remaining of bootargs */
- if (p) {
- p = strstr(p, " ");
- if (p) {
- strcpy(cmdline + n, p);
- n += strlen(p);
- }
- }
- /* append `bootdev=2' */
- #define CMDLINE_BDEV " bootdev="
- if (rootdev > 0 && !strstr(cmdline, CMDLINE_BDEV))
- n += sprintf(cmdline + n, "%s2", CMDLINE_BDEV);
- /* finally, let's update uboot env & save it */
- if (bootargs && strncmp(cmdline, bootargs, sizeof(cmdline))) {
- env_set("bootargs", cmdline);
- need_save = 1;
- }
- __exit:
- if (need_save)
- env_save();
- }
- /* --------------------------------------------------------------------------
- * call from u-boot
- */
- int board_early_init_f(void)
- {
- return 0;
- }
- int board_init(void)
- {
- bd_hwrev_init();
- bd_base_rev_init();
- bd_bootdev_init();
- #ifdef CONFIG_S5P4418_ONEWIRE
- bd_onewire_init();
- #endif
- bd_backlight_off();
- bd_lcd_config_gpio();
- bd_lcd_init();
- if (IS_ENABLED(CONFIG_SILENT_CONSOLE))
- gd->flags |= GD_FLG_SILENT;
- return 0;
- }
- #ifdef CONFIG_BOARD_LATE_INIT
- int board_late_init(void)
- {
- bd_update_env();
- #ifdef CONFIG_REVISION_TAG
- set_board_rev();
- #endif
- set_dtb_name();
- set_ether_addr();
- if (IS_ENABLED(CONFIG_SILENT_CONSOLE))
- gd->flags &= ~GD_FLG_SILENT;
- bd_backlight_on();
- printf("\n");
- return 0;
- }
- #endif
- #ifdef CONFIG_SPLASH_SOURCE
- #include <splash.h>
- static struct splash_location splash_locations[] = {
- {
- .name = "mmc_fs",
- .storage = SPLASH_STORAGE_MMC,
- .flags = SPLASH_STORAGE_FS,
- .devpart = __stringify(CONFIG_ROOT_DEV) ":"
- __stringify(CONFIG_BOOT_PART),
- },
- };
- int splash_screen_prepare(void)
- {
- int err;
- char *env_cmd = env_get("load_splash");
- debug("%s()\n", __func__);
- if (env_cmd) {
- err = run_command(env_cmd, 0);
- } else {
- char devpart[64] = { 0, };
- int bootpart = env_get_ulong("bootpart", 0, CONFIG_BOOT_PART);
- int rootdev;
- if (env_get("firstboot"))
- rootdev = env_get_ulong("rootdev", 0, CONFIG_ROOT_DEV);
- else
- rootdev = board_mmc_bootdev();
- snprintf(devpart, ARRAY_SIZE(devpart), "%d:%d", rootdev,
- bootpart);
- splash_locations[0].devpart = devpart;
- err = splash_source_load(splash_locations,
- ARRAY_SIZE(splash_locations));
- }
- if (!err) {
- char addr[64];
- sprintf(addr, "0x%lx", gd->fb_base);
- env_set("fb_addr", addr);
- }
- return err;
- }
- #endif
- /* u-boot dram initialize */
- int dram_init(void)
- {
- gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
- return 0;
- }
- /* u-boot dram board specific */
- int dram_init_banksize(void)
- {
- #define SCR_USER_SIG6_READ (SCR_ALIVE_BASE + 0x0F0)
- unsigned int reg_val = readl(SCR_USER_SIG6_READ);
- /* set global data memory */
- gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x00000100;
- gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
- gd->bd->bi_dram[0].size = CONFIG_SYS_SDRAM_SIZE;
- /* Number of Row: 14 bits */
- if ((reg_val >> 28) == 14)
- gd->bd->bi_dram[0].size -= 0x20000000;
- /* Number of Memory Chips */
- if ((reg_val & 0x3) > 1) {
- gd->bd->bi_dram[1].start = 0x80000000;
- gd->bd->bi_dram[1].size = 0x40000000;
- }
- return 0;
- }
- #if defined(CONFIG_OF_BOARD_SETUP)
- int ft_board_setup(void *blob, struct bd_info *bd)
- {
- int nodeoff;
- unsigned int rootdev;
- unsigned int fb_addr;
- if (board_mmc_bootdev() > 0) {
- rootdev = fdt_getprop_u32_default(blob, "/board", "sdidx", 2);
- if (rootdev) {
- /* find or create "/chosen" node. */
- nodeoff = fdt_find_or_add_subnode(blob, 0, "chosen");
- if (nodeoff >= 0)
- fdt_setprop_u32(blob, nodeoff, "linux,rootdev",
- rootdev);
- }
- }
- fb_addr = env_get_ulong("fb_addr", 0, 0);
- if (fb_addr) {
- nodeoff = fdt_path_offset(blob, "/reserved-memory");
- if (nodeoff < 0)
- return nodeoff;
- nodeoff = fdt_add_subnode(blob, nodeoff, "display_reserved");
- if (nodeoff >= 0) {
- fdt32_t cells[2];
- cells[0] = cpu_to_fdt32(fb_addr);
- cells[1] = cpu_to_fdt32(0x800000);
- fdt_setprop(blob, nodeoff, "reg", cells,
- sizeof(cells[0]) * 2);
- }
- }
- return 0;
- }
- #endif
|