| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * (C) Copyright 2000-2003 |
| * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
| */ |
| |
| /* |
| * MPC8xx Internal Memory Map Functions |
| */ |
| |
| #include <command.h> |
| #include <asm/global_data.h> |
| |
| #include <asm/immap_8xx.h> |
| #include <asm/cpm_8xx.h> |
| #include <asm/iopin_8xx.h> |
| #include <asm/io.h> |
| #include <asm/ppc.h> |
| |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| static int do_siuinfo(struct cmd_tbl *cmdtp, int flag, int argc, |
| char *const argv[]) |
| { |
| immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; |
| sysconf8xx_t __iomem *sc = &immap->im_siu_conf; |
| |
| printf("SIUMCR= %08x SYPCR = %08x\n", |
| in_be32(&sc->sc_siumcr), in_be32(&sc->sc_sypcr)); |
| printf("SWT = %08x\n", in_be32(&sc->sc_swt)); |
| printf("SIPEND= %08x SIMASK= %08x\n", |
| in_be32(&sc->sc_sipend), in_be32(&sc->sc_simask)); |
| printf("SIEL = %08x SIVEC = %08x\n", |
| in_be32(&sc->sc_siel), in_be32(&sc->sc_sivec)); |
| printf("TESR = %08x SDCR = %08x\n", |
| in_be32(&sc->sc_tesr), in_be32(&sc->sc_sdcr)); |
| return 0; |
| } |
| |
| static int do_memcinfo(struct cmd_tbl *cmdtp, int flag, int argc, |
| char *const argv[]) |
| { |
| immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; |
| memctl8xx_t __iomem *memctl = &immap->im_memctl; |
| int nbanks = 8; |
| uint __iomem *p = &memctl->memc_br0; |
| int i; |
| |
| for (i = 0; i < nbanks; i++, p += 2) |
| printf("BR%-2d = %08x OR%-2d = %08x\n", |
| i, in_be32(p), i, in_be32(p + 1)); |
| |
| printf("MAR = %08x", in_be32(&memctl->memc_mar)); |
| printf(" MCR = %08x\n", in_be32(&memctl->memc_mcr)); |
| printf("MAMR = %08x MBMR = %08x", |
| in_be32(&memctl->memc_mamr), in_be32(&memctl->memc_mbmr)); |
| printf("\nMSTAT = %04x\n", in_be16(&memctl->memc_mstat)); |
| printf("MPTPR = %04x MDR = %08x\n", |
| in_be16(&memctl->memc_mptpr), in_be32(&memctl->memc_mdr)); |
| return 0; |
| } |
| |
| static int do_carinfo(struct cmd_tbl *cmdtp, int flag, int argc, |
| char *const argv[]) |
| { |
| immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; |
| car8xx_t __iomem *car = &immap->im_clkrst; |
| |
| printf("SCCR = %08x\n", in_be32(&car->car_sccr)); |
| printf("PLPRCR= %08x\n", in_be32(&car->car_plprcr)); |
| printf("RSR = %08x\n", in_be32(&car->car_rsr)); |
| return 0; |
| } |
| |
| static int counter; |
| |
| static void header(void) |
| { |
| char *data = "\ |
| -------------------------------- --------------------------------\ |
| 00000000001111111111222222222233 00000000001111111111222222222233\ |
| 01234567890123456789012345678901 01234567890123456789012345678901\ |
| -------------------------------- --------------------------------\ |
| "; |
| int i; |
| |
| if (counter % 2) |
| putc('\n'); |
| counter = 0; |
| |
| for (i = 0; i < 4; i++, data += 79) |
| printf("%.79s\n", data); |
| } |
| |
| static void binary(char *label, uint value, int nbits) |
| { |
| uint mask = 1 << (nbits - 1); |
| int i, second = (counter++ % 2); |
| |
| if (second) |
| putc(' '); |
| puts(label); |
| for (i = 32 + 1; i != nbits; i--) |
| putc(' '); |
| |
| while (mask != 0) { |
| if (value & mask) |
| putc('1'); |
| else |
| putc('0'); |
| mask >>= 1; |
| } |
| |
| if (second) |
| putc('\n'); |
| } |
| |
| #define PA_NBITS 16 |
| #define PA_NB_ODR 8 |
| #define PB_NBITS 18 |
| #define PB_NB_ODR 16 |
| #define PC_NBITS 12 |
| #define PD_NBITS 13 |
| |
| static int do_iopinfo(struct cmd_tbl *cmdtp, int flag, int argc, |
| char *const argv[]) |
| { |
| immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; |
| iop8xx_t __iomem *iop = &immap->im_ioport; |
| ushort __iomem *l, *r; |
| uint __iomem *R; |
| |
| counter = 0; |
| header(); |
| |
| /* |
| * Ports A & B |
| */ |
| |
| l = &iop->iop_padir; |
| R = &immap->im_cpm.cp_pbdir; |
| binary("PA_DIR", in_be16(l++), PA_NBITS); |
| binary("PB_DIR", in_be32(R++), PB_NBITS); |
| binary("PA_PAR", in_be16(l++), PA_NBITS); |
| binary("PB_PAR", in_be32(R++), PB_NBITS); |
| binary("PA_ODR", in_be16(l++), PA_NB_ODR); |
| binary("PB_ODR", in_be32(R++), PB_NB_ODR); |
| binary("PA_DAT", in_be16(l++), PA_NBITS); |
| binary("PB_DAT", in_be32(R++), PB_NBITS); |
| |
| header(); |
| |
| /* |
| * Ports C & D |
| */ |
| |
| l = &iop->iop_pcdir; |
| r = &iop->iop_pddir; |
| binary("PC_DIR", in_be16(l++), PC_NBITS); |
| binary("PD_DIR", in_be16(r++), PD_NBITS); |
| binary("PC_PAR", in_be16(l++), PC_NBITS); |
| binary("PD_PAR", in_be16(r++), PD_NBITS); |
| binary("PC_SO ", in_be16(l++), PC_NBITS); |
| binary(" ", 0, 0); |
| r++; |
| binary("PC_DAT", in_be16(l++), PC_NBITS); |
| binary("PD_DAT", in_be16(r++), PD_NBITS); |
| binary("PC_INT", in_be16(l++), PC_NBITS); |
| |
| header(); |
| return 0; |
| } |
| |
| /* |
| * set the io pins |
| * this needs a clean up for smaller tighter code |
| * use *uint and set the address based on cmd + port |
| */ |
| static int do_iopset(struct cmd_tbl *cmdtp, int flag, int argc, |
| char *const argv[]) |
| { |
| uint rcode = 0; |
| iopin_t iopin; |
| static uint port; |
| static uint pin; |
| static uint value; |
| static enum { |
| DIR, |
| PAR, |
| SOR, |
| ODR, |
| DAT, |
| INT |
| } cmd = DAT; |
| |
| if (argc != 5) { |
| puts("iopset PORT PIN CMD VALUE\n"); |
| return 1; |
| } |
| port = argv[1][0] - 'A'; |
| if (port > 3) |
| port -= 0x20; |
| if (port > 3) |
| rcode = 1; |
| pin = simple_strtol(argv[2], NULL, 10); |
| if (pin > 31) |
| rcode = 1; |
| |
| |
| switch (argv[3][0]) { |
| case 'd': |
| if (argv[3][1] == 'a') |
| cmd = DAT; |
| else if (argv[3][1] == 'i') |
| cmd = DIR; |
| else |
| rcode = 1; |
| break; |
| case 'p': |
| cmd = PAR; |
| break; |
| case 'o': |
| cmd = ODR; |
| break; |
| case 's': |
| cmd = SOR; |
| break; |
| case 'i': |
| cmd = INT; |
| break; |
| default: |
| printf("iopset: unknown command %s\n", argv[3]); |
| rcode = 1; |
| } |
| if (argv[4][0] == '1') |
| value = 1; |
| else if (argv[4][0] == '0') |
| value = 0; |
| else |
| rcode = 1; |
| if (rcode == 0) { |
| iopin.port = port; |
| iopin.pin = pin; |
| iopin.flag = 0; |
| switch (cmd) { |
| case DIR: |
| if (value) |
| iopin_set_out(&iopin); |
| else |
| iopin_set_in(&iopin); |
| break; |
| case PAR: |
| if (value) |
| iopin_set_ded(&iopin); |
| else |
| iopin_set_gen(&iopin); |
| break; |
| case SOR: |
| if (value) |
| iopin_set_opt2(&iopin); |
| else |
| iopin_set_opt1(&iopin); |
| break; |
| case ODR: |
| if (value) |
| iopin_set_odr(&iopin); |
| else |
| iopin_set_act(&iopin); |
| break; |
| case DAT: |
| if (value) |
| iopin_set_high(&iopin); |
| else |
| iopin_set_low(&iopin); |
| break; |
| case INT: |
| if (value) |
| iopin_set_falledge(&iopin); |
| else |
| iopin_set_anyedge(&iopin); |
| break; |
| } |
| } |
| return rcode; |
| } |
| |
| static void prbrg(int n, uint val) |
| { |
| uint extc = (val >> 14) & 3; |
| uint cd = (val & CPM_BRG_CD_MASK) >> 1; |
| uint div16 = (val & CPM_BRG_DIV16) != 0; |
| |
| ulong clock = gd->cpu_clk; |
| |
| printf("BRG%d:", n); |
| |
| if (val & CPM_BRG_RST) |
| puts(" RESET"); |
| else |
| puts(" "); |
| |
| if (val & CPM_BRG_EN) |
| puts(" ENABLED"); |
| else |
| puts(" DISABLED"); |
| |
| printf(" EXTC=%d", extc); |
| |
| if (val & CPM_BRG_ATB) |
| puts(" ATB"); |
| else |
| puts(" "); |
| |
| printf(" DIVIDER=%4d", cd); |
| if (extc == 0 && cd != 0) { |
| uint baudrate; |
| |
| if (div16) |
| baudrate = (clock / 16) / (cd + 1); |
| else |
| baudrate = clock / (cd + 1); |
| |
| printf("=%6d bps", baudrate); |
| } else { |
| puts(" "); |
| } |
| |
| if (val & CPM_BRG_DIV16) |
| puts(" DIV16"); |
| else |
| puts(" "); |
| |
| putc('\n'); |
| } |
| |
| static int do_brginfo(struct cmd_tbl *cmdtp, int flag, int argc, |
| char *const argv[]) |
| { |
| immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; |
| cpm8xx_t __iomem *cp = &immap->im_cpm; |
| uint __iomem *p = &cp->cp_brgc1; |
| int i = 1; |
| |
| while (i <= 4) |
| prbrg(i++, in_be32(p++)); |
| |
| return 0; |
| } |
| |
| #ifdef CONFIG_CMD_REGINFO |
| void print_reginfo(void) |
| { |
| immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; |
| sit8xx_t __iomem *timers = &immap->im_sit; |
| |
| printf("\nSystem Configuration registers\n" |
| "\tIMMR\t0x%08X\n", get_immr()); |
| do_siuinfo(NULL, 0, 0, NULL); |
| |
| printf("Memory Controller Registers\n"); |
| do_memcinfo(NULL, 0, 0, NULL); |
| |
| printf("\nSystem Integration Timers\n"); |
| printf("\tTBSCR\t0x%04X\tRTCSC\t0x%04X\n", |
| in_be16(&timers->sit_tbscr), in_be16(&timers->sit_rtcsc)); |
| printf("\tPISCR\t0x%04X\n", in_be16(&timers->sit_piscr)); |
| } |
| #endif |
| |
| /***************************************************/ |
| |
| U_BOOT_CMD( |
| siuinfo, 1, 1, do_siuinfo, |
| "print System Interface Unit (SIU) registers", |
| "" |
| ); |
| |
| U_BOOT_CMD( |
| memcinfo, 1, 1, do_memcinfo, |
| "print Memory Controller registers", |
| "" |
| ); |
| |
| U_BOOT_CMD( |
| carinfo, 1, 1, do_carinfo, |
| "print Clocks and Reset registers", |
| "" |
| ); |
| |
| U_BOOT_CMD( |
| iopinfo, 1, 1, do_iopinfo, |
| "print I/O Port registers", |
| "" |
| ); |
| |
| U_BOOT_CMD( |
| iopset, 5, 0, do_iopset, |
| "set I/O Port registers", |
| "PORT PIN CMD VALUE\nPORT: A-D, PIN: 0-31, CMD: [dat|dir|odr|sor], VALUE: 0|1" |
| ); |
| |
| U_BOOT_CMD( |
| brginfo, 1, 1, do_brginfo, |
| "print Baud Rate Generator (BRG) registers", |
| "" |
| ); |