spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "n25q016a";
+ compatible = "n25q016a", "spi-flash";
reg = <0>; /* Chip select 0 */
spi-max-frequency = <108000000>;
};
spi-flash@1 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "n25q128a11";
+ compatible = "n25q128a11", "spi-flash";
reg = <1>; /* Chip select 1 */
spi-max-frequency = <108000000>;
u-boot,dm-pre-reloc;
#size-cells = <2>;
ranges;
- cbus: cbus@c1100000 {
+ cbus: bus@c1100000 {
compatible = "simple-bus";
reg = <0x0 0xc1100000 0x0 0x100000>;
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
+ gpio_intc: interrupt-controller@9880 {
+ compatible = "amlogic,meson-gpio-intc";
+ reg = <0x0 0x9880 0x0 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>;
+ status = "disabled";
+ };
+
reset: reset-controller@4404 {
compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset";
- reg = <0x0 0x04404 0x0 0x20>;
+ reg = <0x0 0x04404 0x0 0x9c>;
#reset-cells = <1>;
};
uart_A: serial@84c0 {
- compatible = "amlogic,meson-uart";
- reg = <0x0 0x84c0 0x0 0x14>;
+ compatible = "amlogic,meson-gx-uart";
+ reg = <0x0 0x84c0 0x0 0x18>;
interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>;
status = "disabled";
};
uart_B: serial@84dc {
- compatible = "amlogic,meson-uart";
- reg = <0x0 0x84dc 0x0 0x14>;
+ compatible = "amlogic,meson-gx-uart";
+ reg = <0x0 0x84dc 0x0 0x18>;
interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>;
status = "disabled";
};
};
uart_C: serial@8700 {
- compatible = "amlogic,meson-uart";
- reg = <0x0 0x8700 0x0 0x14>;
+ compatible = "amlogic,meson-gx-uart";
+ reg = <0x0 0x8700 0x0 0x18>;
interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>;
status = "disabled";
};
};
};
- aobus: aobus@c8100000 {
+ aobus: bus@c8100000 {
compatible = "simple-bus";
reg = <0x0 0xc8100000 0x0 0x100000>;
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
- clkc_AO: clock-controller@040 {
- compatible = "amlogic,gx-aoclkc", "amlogic,gxbb-aoclkc";
- reg = <0x0 0x00040 0x0 0x4>;
- #clock-cells = <1>;
- #reset-cells = <1>;
+ sysctrl_AO: sys-ctrl@0 {
+ compatible = "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd";
+ reg = <0x0 0x0 0x0 0x100>;
+
+ pwrc_vpu: power-controller-vpu {
+ compatible = "amlogic,meson-gx-pwrc-vpu";
+ #power-domain-cells = <0>;
+ amlogic,hhi-sysctrl = <&sysctrl>;
+ };
+
+ clkc_AO: clock-controller {
+ compatible = "amlogic,meson-gx-aoclkc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+ };
+
+ cec_AO: cec@100 {
+ compatible = "amlogic,meson-gx-ao-cec";
+ reg = <0x0 0x00100 0x0 0x14>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>;
+ };
+
+ sec_AO: ao-secure@140 {
+ compatible = "amlogic,meson-gx-ao-secure", "syscon";
+ reg = <0x0 0x140 0x0 0x140>;
+ amlogic,has-chip-id;
};
uart_AO: serial@4c0 {
- compatible = "amlogic,meson-uart";
- reg = <0x0 0x004c0 0x0 0x14>;
+ compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart";
+ reg = <0x0 0x004c0 0x0 0x18>;
interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>;
status = "disabled";
};
uart_AO_B: serial@4e0 {
- compatible = "amlogic,meson-uart";
- reg = <0x0 0x004e0 0x0 0x14>;
+ compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart";
+ reg = <0x0 0x004e0 0x0 0x18>;
interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>;
status = "disabled";
};
};
};
- hiubus: hiubus@c883c000 {
+ hiubus: bus@c883c000 {
compatible = "simple-bus";
reg = <0x0 0xc883c000 0x0 0x2000>;
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
+ sysctrl: system-controller@0 {
+ compatible = "amlogic,meson-gx-hhi-sysctrl", "syscon", "simple-mfd";
+ reg = <0 0 0 0x400>;
+ };
+
mailbox: mailbox@404 {
compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
reg = <0 0x404 0 0x4c>;
- interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
- <0 209 IRQ_TYPE_EDGE_RISING>,
- <0 210 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 209 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 210 IRQ_TYPE_EDGE_RISING>;
#mbox-cells = <1>;
};
};
compatible = "amlogic,meson-gx-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac";
reg = <0x0 0xc9410000 0x0 0x10000
0x0 0xc8834540 0x0 0x4>;
- interrupts = <0 8 1>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "macirq";
status = "disabled";
};
/ {
compatible = "hardkernel,odroid-c2", "amlogic,meson-gxbb";
model = "Hardkernel ODROID-C2";
-
+
aliases {
serial0 = &uart_AO;
};
compatible = "mmc-pwrseq-emmc";
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
};
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_tmds_out>;
+ };
+ };
+ };
+};
+
+&cec_AO {
+ status = "okay";
+ pinctrl-0 = <&ao_cec_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
};
ðmac {
#size-cells = <0>;
eth_phy0: ethernet-phy@0 {
+ /* Realtek RTL8211F (0x001cc916) */
reg = <0>;
+ interrupt-parent = <&gpio_intc>;
+ /* MAC_INTR on GPIOZ_15 */
+ interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
eee-broken-1000t;
};
};
};
};
+&hdmi_tx {
+ status = "okay";
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+ pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+ hdmi_tx_tmds_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+};
+
&i2c_A {
status = "okay";
pinctrl-0 = <&i2c_a_pins>;
"USB HUB nRESET", "USB OTG Power En",
"J7 Header Pin2", "IR In", "J7 Header Pin4",
"J7 Header Pin6", "J7 Header Pin5", "J7 Header Pin7",
- "HDMI CEC", "SYS LED";
+ "HDMI CEC", "SYS LED",
+ /* GPIO_TEST_N */
+ "";
};
&pinctrl_periphs {
"J2 Header Pin12", "J2 Header Pin13",
"J2 Header Pin8", "J2 Header Pin10",
"", "", "", "", "",
- "J2 Header Pin11", "", "J2 Header Pin7",
+ "J2 Header Pin11", "", "J2 Header Pin7", "",
/* Bank GPIOCLK */
- "", "", "", "",
- /* GPIO_TEST_N */
- "";
+ "", "", "", "";
};
&saradc {
&sd_emmc_b {
status = "okay";
pinctrl-0 = <&sdcard_pins>;
- pinctrl-names = "default";
+ pinctrl-1 = <&sdcard_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
bus-width = <4>;
cap-sd-highspeed;
/* eMMC */
&sd_emmc_c {
status = "okay";
- pinctrl-0 = <&emmc_pins>;
- pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
bus-width = <8>;
- cap-sd-highspeed;
max-frequency = <200000000>;
non-removable;
disable-wp;
&usb1_phy {
status = "okay";
+ phy-supply = <&usb_otg_pwr>;
};
&usb0 {
};
};
+&cec_AO {
+ clocks = <&clkc_AO CLKID_AO_CEC_32K>;
+ clock-names = "core";
+};
+
+&clkc_AO {
+ compatible = "amlogic,meson-gxbb-aoclkc", "amlogic,meson-gx-aoclkc";
+};
+
ðmac {
clocks = <&clkc CLKID_ETH>,
<&clkc CLKID_FCLK_DIV2>,
clock-names = "stmmaceth", "clkin0", "clkin1";
};
+&gpio_intc {
+ compatible = "amlogic,meson-gpio-intc",
+ "amlogic,meson-gxbb-gpio-intc";
+ status = "okay";
+};
+
&hdmi_tx {
compatible = "amlogic,meson-gxbb-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
resets = <&reset RESET_HDMITX_CAPB3>,
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinctrl_periphs 0 14 120>;
+ gpio-ranges = <&pinctrl_periphs 0 0 119>;
};
emmc_pins: emmc {
mux {
groups = "emmc_nand_d07",
"emmc_cmd",
- "emmc_clk",
- "emmc_ds";
+ "emmc_clk";
+ function = "emmc";
+ };
+ };
+
+ emmc_ds_pins: emmc-ds {
+ mux {
+ groups = "emmc_ds";
function = "emmc";
};
};
+ emmc_clk_gate_pins: emmc_clk_gate {
+ mux {
+ groups = "BOOT_8";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "BOOT_8";
+ bias-pull-down;
+ };
+ };
+
nor_pins: nor {
mux {
groups = "nor_d",
};
};
+ sdcard_clk_gate_pins: sdcard_clk_gate {
+ mux {
+ groups = "CARD_2";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "CARD_2";
+ bias-pull-down;
+ };
+ };
+
sdio_pins: sdio {
mux {
groups = "sdio_d0",
};
};
+ sdio_clk_gate_pins: sdio_clk_gate {
+ mux {
+ groups = "GPIOX_4";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "GPIOX_4";
+ bias-pull-down;
+ };
+ };
+
sdio_irq_pins: sdio_irq {
mux {
groups = "sdio_irq";
};
};
+&pwrc_vpu {
+ resets = <&reset RESET_VIU>,
+ <&reset RESET_VENC>,
+ <&reset RESET_VCBUS>,
+ <&reset RESET_BT656>,
+ <&reset RESET_DVIN_RESET>,
+ <&reset RESET_RDMA>,
+ <&reset RESET_VENCI>,
+ <&reset RESET_VENCP>,
+ <&reset RESET_VDAC>,
+ <&reset RESET_VDI6>,
+ <&reset RESET_VENCL>,
+ <&reset RESET_VID_LOCK>;
+ clocks = <&clkc CLKID_VPU>,
+ <&clkc CLKID_VAPB>;
+ clock-names = "vpu", "vapb";
+ /*
+ * VPU clocking is provided by two identical clock paths
+ * VPU_0 and VPU_1 muxed to a single clock by a glitch
+ * free mux to safely change frequency while running.
+ * Same for VAPB but with a final gate after the glitch free mux.
+ */
+ assigned-clocks = <&clkc CLKID_VPU_0_SEL>,
+ <&clkc CLKID_VPU_0>,
+ <&clkc CLKID_VPU>, /* Glitch free mux */
+ <&clkc CLKID_VAPB_0_SEL>,
+ <&clkc CLKID_VAPB_0>,
+ <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */
+ assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_VPU_0>,
+ <&clkc CLKID_FCLK_DIV4>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_VAPB_0>;
+ assigned-clock-rates = <0>, /* Do Nothing */
+ <666666666>,
+ <0>, /* Do Nothing */
+ <0>, /* Do Nothing */
+ <250000000>,
+ <0>; /* Do Nothing */
+};
+
&saradc {
compatible = "amlogic,meson-gxbb-saradc", "amlogic,meson-saradc";
clocks = <&xtal>,
<&clkc CLKID_SAR_ADC>,
- <&clkc CLKID_SANA>,
<&clkc CLKID_SAR_ADC_CLK>,
<&clkc CLKID_SAR_ADC_SEL>;
- clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
+ clock-names = "clkin", "core", "adc_clk", "adc_sel";
};
&sd_emmc_a {
clocks = <&clkc CLKID_SD_EMMC_A>,
- <&xtal>,
+ <&clkc CLKID_SD_EMMC_A_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
&sd_emmc_b {
clocks = <&clkc CLKID_SD_EMMC_B>,
- <&xtal>,
+ <&clkc CLKID_SD_EMMC_B_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
&sd_emmc_c {
clocks = <&clkc CLKID_SD_EMMC_C>,
- <&xtal>,
+ <&clkc CLKID_SD_EMMC_C_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
clocks = <&clkc CLKID_SPI>;
};
+&uart_A {
+ clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_AO {
+ clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_AO_B {
+ clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_B {
+ clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_C {
+ clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
&vpu {
compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
+ power-domains = <&pwrc_vpu>;
};
};
};
+&cec_AO {
+ status = "okay";
+ pinctrl-0 = <&ao_cec_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
linux,rc-map-name = "rc-geekbox";
};
+&pinctrl_aobus {
+ gpio-line-names = "UART TX",
+ "UART RX",
+ "Power Key In",
+ "J9 Header Pin35",
+ "J9 Header Pin16",
+ "J9 Header Pin15",
+ "J9 Header Pin33",
+ "IR In",
+ "HDMI CEC",
+ "SYS LED",
+ /* GPIO_TEST_N */
+ "";
+};
+
+&pinctrl_periphs {
+ gpio-line-names = /* Bank GPIOZ */
+ "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "",
+ "Power OFF",
+ "VCCK Enable",
+ /* Bank GPIOH */
+ "HDMI HPD", "HDMI SDA", "HDMI SCL",
+ "HDMI_5V_EN", "SPDIF",
+ "J9 Header Pin37",
+ "J9 Header Pin30",
+ "J9 Header Pin29",
+ "J9 Header Pin32",
+ "J9 Header Pin31",
+ /* Bank BOOT */
+ "eMMC D0", "eMMC D1", "eMMC D2", "eMMC D3",
+ "eMMC D4", "eMMC D5", "eMMC D6", "eMMC D7",
+ "eMMC Clk", "eMMC Reset", "eMMC CMD",
+ "", "BOOT_MODE", "", "", "eMMC Data Strobe",
+ /* Bank CARD */
+ "SDCard D1", "SDCard D0", "SDCard CLK", "SDCard CMD",
+ "SDCard D3", "SDCard D2", "SDCard Det",
+ /* Bank GPIODV */
+ "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "",
+ "I2C A SDA", "I2C A SCK", "I2C B SDA", "I2C B SCK",
+ "VCCK Regulator", "VDDEE Regulator",
+ /* Bank GPIOX */
+ "WIFI SDIO D0", "WIFI SDIO D1", "WIFI SDIO D2",
+ "WIFI SDIO D3", "WIFI SDIO CLK", "WIFI SDIO CMD",
+ "WIFI Power Enable", "WIFI WAKE HOST",
+ "Bluetooth PCM DOUT", "Bluetooth PCM DIN",
+ "Bluetooth PCM SYNC", "Bluetooth PCM CLK",
+ "Bluetooth UART TX", "Bluetooth UART RX",
+ "Bluetooth UART CTS", "Bluetooth UART RTS",
+ "WIFI 32K", "Bluetooth Enable",
+ "Bluetooth WAKE HOST",
+ /* Bank GPIOCLK */
+ "", "J9 Header Pin39";
+};
+
&pwm_AO_ab {
status = "okay";
pinctrl-0 = <&pwm_ao_a_3_pins>, <&pwm_ao_b_pins>;
reg = <0x0 0x0 0x0 0x80000000>;
};
+ hdmi_5v: regulator-hdmi-5v {
+ compatible = "regulator-fixed";
+
+ regulator-name = "HDMI_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio GPIOH_3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
vcc_3v3: regulator-vcc_3v3 {
compatible = "regulator-fixed";
regulator-name = "VCC_3V3";
states = <3300000 0>,
<1800000 1>;
+
+ regulator-settling-time-up-us = <200>;
+ regulator-settling-time-down-us = <50000>;
+ };
+
+ vddio_ao18: regulator-vddio_ao18 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDIO_AO18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
};
vddio_boot: regulator-vddio_boot {
};
};
+&cec_AO {
+ status = "okay";
+ pinctrl-0 = <&ao_cec_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
status = "okay";
};
+&internal_phy {
+ pinctrl-0 = <ð_link_led_pins>, <ð_act_led_pins>;
+ pinctrl-names = "default";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
};
};
+&pinctrl_aobus {
+ gpio-line-names = "UART TX",
+ "UART RX",
+ "Blue LED",
+ "SDCard Voltage Switch",
+ "7J1 Header Pin5",
+ "7J1 Header Pin3",
+ "7J1 Header Pin12",
+ "IR In",
+ "9J3 Switch HDMI CEC/7J1 Header Pin11",
+ "7J1 Header Pin13",
+ /* GPIO_TEST_N */
+ "7J1 Header Pin15";
+};
+
+&pinctrl_periphs {
+ gpio-line-names = /* Bank GPIOZ */
+ "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "",
+ "Eth Link LED", "Eth Activity LED",
+ /* Bank GPIOH */
+ "HDMI HPD", "HDMI SDA", "HDMI SCL",
+ "HDMI_5V_EN", "9J1 Header Pin2",
+ "Analog Audio Mute",
+ "2J3 Header Pin6",
+ "2J3 Header Pin5",
+ "2J3 Header Pin4",
+ "2J3 Header Pin3",
+ /* Bank BOOT */
+ "eMMC D0", "eMMC D1", "eMMC D2", "eMMC D3",
+ "eMMC D4", "eMMC D5", "eMMC D6", "eMMC D7",
+ "eMMC Clk", "eMMC Reset", "eMMC CMD",
+ "ALT BOOT MODE", "", "", "", "eMMC Data Strobe",
+ /* Bank CARD */
+ "SDCard D1", "SDCard D0", "SDCard CLK", "SDCard CMD",
+ "SDCard D3", "SDCard D2", "SDCard Det",
+ /* Bank GPIODV */
+ "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "",
+ "Green LED", "VCCK Enable",
+ "7J1 Header Pin27", "7J1 Header Pin28",
+ "VCCK Regulator", "VDDEE Regulator",
+ /* Bank GPIOX */
+ "7J1 Header Pin22", "7J1 Header Pin26",
+ "7J1 Header Pin36", "7J1 Header Pin38",
+ "7J1 Header Pin40", "7J1 Header Pin37",
+ "7J1 Header Pin33", "7J1 Header Pin35",
+ "7J1 Header Pin19", "7J1 Header Pin21",
+ "7J1 Header Pin24", "7J1 Header Pin23",
+ "7J1 Header Pin8", "7J1 Header Pin10",
+ "7J1 Header Pin16", "7J1 Header Pin18",
+ "7J1 Header Pin32", "7J1 Header Pin29",
+ "7J1 Header Pin31",
+ /* Bank GPIOCLK */
+ "7J1 Header Pin7", "";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddio_ao18>;
+};
+
/* SD card */
&sd_emmc_b {
status = "okay";
pinctrl-0 = <&sdcard_pins>;
- pinctrl-names = "default";
+ pinctrl-1 = <&sdcard_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
bus-width = <4>;
cap-sd-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
max-frequency = <100000000>;
disable-wp;
/* eMMC */
&sd_emmc_c {
status = "okay";
- pinctrl-0 = <&emmc_pins>;
- pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
bus-width = <8>;
cap-mmc-highspeed;
+ mmc-ddr-3_3v;
max-frequency = <50000000>;
non-removable;
disable-wp;
};
};
+&cec_AO {
+ status = "okay";
+ pinctrl-0 = <&ao_cec_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
reg = <0x0 0x0 0x0 0x80000000>;
};
+ hdmi_5v: regulator-hdmi-5v {
+ compatible = "regulator-fixed";
+
+ regulator-name = "HDMI_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio GPIOH_3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
vddio_boot: regulator-vddio_boot {
compatible = "regulator-fixed";
regulator-name = "VDDIO_BOOT";
&sd_emmc_a {
status = "okay";
pinctrl-0 = <&sdio_pins>;
- pinctrl-names = "default";
+ pinctrl-1 = <&sdio_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
#address-cells = <1>;
#size-cells = <0>;
&sd_emmc_b {
status = "okay";
pinctrl-0 = <&sdcard_pins>;
- pinctrl-names = "default";
+ pinctrl-1 = <&sdcard_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
bus-width = <4>;
cap-sd-highspeed;
/* eMMC */
&sd_emmc_c {
status = "okay";
- pinctrl-0 = <&emmc_pins>;
- pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
bus-width = <8>;
- cap-sd-highspeed;
cap-mmc-highspeed;
max-frequency = <200000000>;
non-removable;
#include "meson-gx.dtsi"
#include <dt-bindings/clock/gxbb-clkc.h>
+#include <dt-bindings/clock/gxbb-aoclkc.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>
#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
/ {
compatible = "amlogic,meson-gxl";
+
+ reserved-memory {
+ /* Alternate 3 MiB reserved for ARM Trusted Firmware (BL31) */
+ secmon_reserved_alt: secmon@5000000 {
+ reg = <0x0 0x05000000 0x0 0x300000>;
+ no-map;
+ };
+ };
};
ðmac {
};
};
+&cec_AO {
+ clocks = <&clkc_AO CLKID_AO_CEC_32K>;
+ clock-names = "core";
+};
+
+&clkc_AO {
+ compatible = "amlogic,meson-gxl-aoclkc", "amlogic,meson-gx-aoclkc";
+};
+
+&gpio_intc {
+ compatible = "amlogic,meson-gpio-intc",
+ "amlogic,meson-gxl-gpio-intc";
+ status = "okay";
+};
+
&hdmi_tx {
compatible = "amlogic,meson-gxl-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
resets = <&reset RESET_HDMITX_CAPB3>,
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinctrl_periphs 0 10 101>;
+ gpio-ranges = <&pinctrl_periphs 0 0 100>;
};
emmc_pins: emmc {
mux {
groups = "emmc_nand_d07",
"emmc_cmd",
- "emmc_clk",
- "emmc_ds";
+ "emmc_clk";
function = "emmc";
};
};
+ emmc_ds_pins: emmc-ds {
+ mux {
+ groups = "emmc_ds";
+ function = "emmc";
+ };
+ };
+
+ emmc_clk_gate_pins: emmc_clk_gate {
+ mux {
+ groups = "BOOT_8";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "BOOT_8";
+ bias-pull-down;
+ };
+ };
+
nor_pins: nor {
mux {
groups = "nor_d",
};
};
+ sdcard_clk_gate_pins: sdcard_clk_gate {
+ mux {
+ groups = "CARD_2";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "CARD_2";
+ bias-pull-down;
+ };
+ };
+
sdio_pins: sdio {
mux {
groups = "sdio_d0",
};
};
+ sdio_clk_gate_pins: sdio_clk_gate {
+ mux {
+ groups = "GPIOX_4";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "GPIOX_4";
+ bias-pull-down;
+ };
+ };
+
sdio_irq_pins: sdio_irq {
mux {
groups = "sdio_irq";
internal_phy: ethernet-phy@8 {
compatible = "ethernet-phy-id0181.4400", "ethernet-phy-ieee802.3-c22";
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
reg = <8>;
max-speed = <100>;
};
};
};
+&pwrc_vpu {
+ resets = <&reset RESET_VIU>,
+ <&reset RESET_VENC>,
+ <&reset RESET_VCBUS>,
+ <&reset RESET_BT656>,
+ <&reset RESET_DVIN_RESET>,
+ <&reset RESET_RDMA>,
+ <&reset RESET_VENCI>,
+ <&reset RESET_VENCP>,
+ <&reset RESET_VDAC>,
+ <&reset RESET_VDI6>,
+ <&reset RESET_VENCL>,
+ <&reset RESET_VID_LOCK>;
+ clocks = <&clkc CLKID_VPU>,
+ <&clkc CLKID_VAPB>;
+ clock-names = "vpu", "vapb";
+ /*
+ * VPU clocking is provided by two identical clock paths
+ * VPU_0 and VPU_1 muxed to a single clock by a glitch
+ * free mux to safely change frequency while running.
+ * Same for VAPB but with a final gate after the glitch free mux.
+ */
+ assigned-clocks = <&clkc CLKID_VPU_0_SEL>,
+ <&clkc CLKID_VPU_0>,
+ <&clkc CLKID_VPU>, /* Glitch free mux */
+ <&clkc CLKID_VAPB_0_SEL>,
+ <&clkc CLKID_VAPB_0>,
+ <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */
+ assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_VPU_0>,
+ <&clkc CLKID_FCLK_DIV4>,
+ <0>, /* Do Nothing */
+ <&clkc CLKID_VAPB_0>;
+ assigned-clock-rates = <0>, /* Do Nothing */
+ <666666666>,
+ <0>, /* Do Nothing */
+ <0>, /* Do Nothing */
+ <250000000>,
+ <0>; /* Do Nothing */
+};
+
&saradc {
compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
clocks = <&xtal>,
<&clkc CLKID_SAR_ADC>,
- <&clkc CLKID_SANA>,
<&clkc CLKID_SAR_ADC_CLK>,
<&clkc CLKID_SAR_ADC_SEL>;
- clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
+ clock-names = "clkin", "core", "adc_clk", "adc_sel";
};
&sd_emmc_a {
clocks = <&clkc CLKID_SD_EMMC_A>,
- <&xtal>,
+ <&clkc CLKID_SD_EMMC_A_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
&sd_emmc_b {
clocks = <&clkc CLKID_SD_EMMC_B>,
- <&xtal>,
+ <&clkc CLKID_SD_EMMC_B_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
&sd_emmc_c {
clocks = <&clkc CLKID_SD_EMMC_C>,
- <&xtal>,
+ <&clkc CLKID_SD_EMMC_C_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
clocks = <&clkc CLKID_SPI>;
};
+&uart_A {
+ clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_AO {
+ clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_AO_B {
+ clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_B {
+ clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
+&uart_C {
+ clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>;
+ clock-names = "xtal", "pclk", "baud";
+};
+
&vpu {
compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
+ power-domains = <&pwrc_vpu>;
};
};
};
+ pwr: pwr@50001000 {
+ compatible = "st,stm32mp1-pwr", "st,stm32-pwr", "syscon", "simple-mfd";
+ reg = <0x50001000 0x400>;
+ system-power-controller;
+ interrupts = <GIC_SPI 149 IRQ_TYPE_NONE>;
+ st,sysrcc = <&rcc>;
+ clocks = <&rcc_clk PLL2_R>;
+ clock-names = "phyclk";
+
+ pwr-regulators@c {
+ compatible = "st,stm32mp1,pwr-reg";
+ st,tzcr = <&rcc 0x0 0x1>;
+
+ reg11: reg11 {
+ regulator-name = "reg11";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ reg18: reg18 {
+ regulator-name = "reg18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ usb33: usb33 {
+ regulator-name = "usb33";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+
+ vrefbuf: vrefbuf@50025000 {
+ compatible = "st,stm32-vrefbuf";
+ reg = <0x50025000 0x8>;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2500000>;
+ clocks = <&rcc_clk VREF>;
+ status = "disabled";
+ };
+
pinctrl: pin-controller {
compatible = "st,stm32mp157-pinctrl";
#address-cells = <1>;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+#include <dt-bindings/mfd/st,stpmu1.h>
/ {
model = "STMicroelectronics STM32MP157C pmic eval daughter";
memory {
reg = <0xC0000000 0x40000000>;
};
+
+ sd_switch: regulator-sd_switch {
+ compatible = "regulator-gpio";
+ regulator-name = "sd_switch";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-type = "voltage";
+ regulator-always-on;
+
+ gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>;
+ gpios-states = <0>;
+ states = <1800000 0x1 2900000 0x0>;
+ };
};
&gpioa {
interrupt-controller;
#interrupt-cells = <2>;
status = "okay";
+
+ st,main_control_register = <0x04>;
+ st,vin_control_register = <0xc0>;
+ st,usb_control_register = <0x30>;
+
+ regulators {
+ compatible = "st,stpmu1-regulators";
+
+ ldo1-supply = <&v3v3>;
+ ldo2-supply = <&v3v3>;
+ ldo3-supply = <&vdd_ddr>;
+ ldo5-supply = <&v3v3>;
+ ldo6-supply = <&v3v3>;
+ pwr_sw1-supply = <&bst_out>;
+ pwr_sw2-supply = <&bst_out>;
+
+ vddcore: buck1 {
+ regulator-name = "vddcore";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <2>;
+ regulator-over-current-protection;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1200000>;
+ regulator-mode = <8>;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr: buck2 {
+ regulator-name = "vdd_ddr";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <2>;
+ regulator-over-current-protection;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <1350000>;
+ regulator-on-in-suspend;
+ regulator-mode = <8>;
+ };
+ regulator-state-mem {
+ regulator-suspend-microvolt = <1350000>;
+ regulator-on-in-suspend;
+ regulator-mode = <8>;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd: buck3 {
+ regulator-name = "vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ st,mask_reset;
+ regulator-initial-mode = <8>;
+ regulator-over-current-protection;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ regulator-mode = <8>;
+ };
+ regulator-state-mem {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ regulator-mode = <8>;
+ };
+ regulator-state-disk {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ regulator-mode = <8>;
+ };
+ };
+
+ v3v3: buck4 {
+ regulator-name = "v3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-over-current-protection;
+ regulator-initial-mode = <8>;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-unchanged-in-suspend;
+ regulator-mode = <8>;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda: ldo1 {
+ regulator-name = "vdda";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ interrupts = <IT_CURLIM_LDO1 0>;
+ interrupt-parent = <&pmic>;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <2900000>;
+ regulator-unchanged-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ v2v8: ldo2 {
+ regulator-name = "v2v8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ interrupts = <IT_CURLIM_LDO2 0>;
+ interrupt-parent = <&pmic>;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <2800000>;
+ regulator-unchanged-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vtt_ddr: ldo3 {
+ regulator-name = "vtt_ddr";
+ regulator-min-microvolt = <0000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-over-current-protection;
+
+ regulator-state-standby {
+ regulator-off-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_usb: ldo4 {
+ regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ interrupts = <IT_CURLIM_LDO4 0>;
+ interrupt-parent = <&pmic>;
+
+ regulator-state-standby {
+ regulator-unchanged-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_sd: ldo5 {
+ regulator-name = "vdd_sd";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ interrupts = <IT_CURLIM_LDO5 0>;
+ interrupt-parent = <&pmic>;
+ regulator-boot-on;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <2900000>;
+ regulator-unchanged-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ v1v8: ldo6 {
+ regulator-name = "v1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ interrupts = <IT_CURLIM_LDO6 0>;
+ interrupt-parent = <&pmic>;
+
+ regulator-state-standby {
+ regulator-suspend-microvolt = <1800000>;
+ regulator-unchanged-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vref_ddr: vref_ddr {
+ regulator-name = "vref_ddr";
+ regulator-always-on;
+ regulator-over-current-protection;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+
+ bst_out: boost {
+ regulator-name = "bst_out";
+ interrupts = <IT_OCP_BOOST 0>;
+ interrupt-parent = <&pmic>;
+ };
+
+ vbus_otg: pwr_sw1 {
+ regulator-name = "vbus_otg";
+ interrupts = <IT_OCP_OTG 0>;
+ interrupt-parent = <&pmic>;
+ regulator-active-discharge;
+ };
+
+ vbus_sw: pwr_sw2 {
+ regulator-name = "vbus_sw";
+ interrupts = <IT_OCP_SWOUT 0>;
+ interrupt-parent = <&pmic>;
+ regulator-active-discharge;
+ };
+ };
};
};
st,negedge;
st,pin-ckin;
bus-width = <4>;
+ vmmc-supply = <&vdd_sd>;
+ vqmmc-supply = <&sd_switch>;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
+ */
+
+#ifndef __GX_H__
+#define __GX_H__
+
+#define GX_FIRMWARE_MEM_SIZE 0x1000000
+
+#define GX_AOBUS_BASE 0xc8100000
+#define GX_PERIPHS_BASE 0xc8834400
+#define GX_HIU_BASE 0xc883c000
+#define GX_ETH_BASE 0xc9410000
+
+/* Always-On Peripherals registers */
+#define GX_AO_ADDR(off) (GX_AOBUS_BASE + ((off) << 2))
+
+#define GX_AO_SEC_GP_CFG0 GX_AO_ADDR(0x90)
+#define GX_AO_SEC_GP_CFG3 GX_AO_ADDR(0x93)
+#define GX_AO_SEC_GP_CFG4 GX_AO_ADDR(0x94)
+#define GX_AO_SEC_GP_CFG5 GX_AO_ADDR(0x95)
+
+#define GX_AO_MEM_SIZE_MASK 0xFFFF0000
+#define GX_AO_MEM_SIZE_SHIFT 16
+#define GX_AO_BL31_RSVMEM_SIZE_MASK 0xFFFF0000
+#define GX_AO_BL31_RSVMEM_SIZE_SHIFT 16
+#define GX_AO_BL32_RSVMEM_SIZE_MASK 0xFFFF
+
+/* Peripherals registers */
+#define GX_PERIPHS_ADDR(off) (GX_PERIPHS_BASE + ((off) << 2))
+
+/* GPIO registers 0 to 6 */
+#define _GX_GPIO_OFF(n) ((n) == 6 ? 0x08 : 0x0c + 3 * (n))
+#define GX_GPIO_EN(n) GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 0)
+#define GX_GPIO_IN(n) GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 1)
+#define GX_GPIO_OUT(n) GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 2)
+
+#define GX_ETH_REG_0 GX_PERIPHS_ADDR(0x50)
+#define GX_ETH_REG_1 GX_PERIPHS_ADDR(0x51)
+#define GX_ETH_REG_2 GX_PERIPHS_ADDR(0x56)
+#define GX_ETH_REG_3 GX_PERIPHS_ADDR(0x57)
+
+#define GX_ETH_REG_0_PHY_INTF BIT(0)
+#define GX_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5)
+#define GX_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7)
+#define GX_ETH_REG_0_PHY_CLK_EN BIT(10)
+#define GX_ETH_REG_0_INVERT_RMII_CLK BIT(11)
+#define GX_ETH_REG_0_CLK_EN BIT(12)
+
+/* HIU registers */
+#define GX_HIU_ADDR(off) (GX_HIU_BASE + ((off) << 2))
+
+#define GX_MEM_PD_REG_0 GX_HIU_ADDR(0x40)
+
+/* Ethernet memory power domain */
+#define GX_MEM_PD_REG_0_ETH_MASK (BIT(2) | BIT(3))
+
+/* Clock gates */
+#define GX_GCLK_MPEG_0 GX_HIU_ADDR(0x50)
+#define GX_GCLK_MPEG_1 GX_HIU_ADDR(0x51)
+#define GX_GCLK_MPEG_2 GX_HIU_ADDR(0x52)
+#define GX_GCLK_MPEG_OTHER GX_HIU_ADDR(0x53)
+#define GX_GCLK_MPEG_AO GX_HIU_ADDR(0x54)
+
+#define GX_GCLK_MPEG_0_I2C BIT(9)
+#define GX_GCLK_MPEG_1_ETH BIT(3)
+
+#endif /* __GX_H__ */
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
- */
-
-#ifndef __GXBB_H__
-#define __GXBB_H__
-
-#define GXBB_FIRMWARE_MEM_SIZE 0x1000000
-
-#define GXBB_AOBUS_BASE 0xc8100000
-#define GXBB_PERIPHS_BASE 0xc8834400
-#define GXBB_HIU_BASE 0xc883c000
-#define GXBB_ETH_BASE 0xc9410000
-
-/* Always-On Peripherals registers */
-#define GXBB_AO_ADDR(off) (GXBB_AOBUS_BASE + ((off) << 2))
-
-#define GXBB_AO_SEC_GP_CFG0 GXBB_AO_ADDR(0x90)
-#define GXBB_AO_SEC_GP_CFG3 GXBB_AO_ADDR(0x93)
-#define GXBB_AO_SEC_GP_CFG4 GXBB_AO_ADDR(0x94)
-#define GXBB_AO_SEC_GP_CFG5 GXBB_AO_ADDR(0x95)
-
-#define GXBB_AO_MEM_SIZE_MASK 0xFFFF0000
-#define GXBB_AO_MEM_SIZE_SHIFT 16
-#define GXBB_AO_BL31_RSVMEM_SIZE_MASK 0xFFFF0000
-#define GXBB_AO_BL31_RSVMEM_SIZE_SHIFT 16
-#define GXBB_AO_BL32_RSVMEM_SIZE_MASK 0xFFFF
-
-/* Peripherals registers */
-#define GXBB_PERIPHS_ADDR(off) (GXBB_PERIPHS_BASE + ((off) << 2))
-
-/* GPIO registers 0 to 6 */
-#define _GXBB_GPIO_OFF(n) ((n) == 6 ? 0x08 : 0x0c + 3 * (n))
-#define GXBB_GPIO_EN(n) GXBB_PERIPHS_ADDR(_GXBB_GPIO_OFF(n) + 0)
-#define GXBB_GPIO_IN(n) GXBB_PERIPHS_ADDR(_GXBB_GPIO_OFF(n) + 1)
-#define GXBB_GPIO_OUT(n) GXBB_PERIPHS_ADDR(_GXBB_GPIO_OFF(n) + 2)
-
-#define GXBB_ETH_REG_0 GXBB_PERIPHS_ADDR(0x50)
-#define GXBB_ETH_REG_1 GXBB_PERIPHS_ADDR(0x51)
-#define GXBB_ETH_REG_2 GXBB_PERIPHS_ADDR(0x56)
-#define GXBB_ETH_REG_3 GXBB_PERIPHS_ADDR(0x57)
-
-#define GXBB_ETH_REG_0_PHY_INTF BIT(0)
-#define GXBB_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5)
-#define GXBB_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7)
-#define GXBB_ETH_REG_0_PHY_CLK_EN BIT(10)
-#define GXBB_ETH_REG_0_INVERT_RMII_CLK BIT(11)
-#define GXBB_ETH_REG_0_CLK_EN BIT(12)
-
-/* HIU registers */
-#define GXBB_HIU_ADDR(off) (GXBB_HIU_BASE + ((off) << 2))
-
-#define GXBB_MEM_PD_REG_0 GXBB_HIU_ADDR(0x40)
-
-/* Ethernet memory power domain */
-#define GXBB_MEM_PD_REG_0_ETH_MASK (BIT(2) | BIT(3))
-
-/* Clock gates */
-#define GXBB_GCLK_MPEG_0 GXBB_HIU_ADDR(0x50)
-#define GXBB_GCLK_MPEG_1 GXBB_HIU_ADDR(0x51)
-#define GXBB_GCLK_MPEG_2 GXBB_HIU_ADDR(0x52)
-#define GXBB_GCLK_MPEG_OTHER GXBB_HIU_ADDR(0x53)
-#define GXBB_GCLK_MPEG_AO GXBB_HIU_ADDR(0x54)
-
-#define GXBB_GCLK_MPEG_0_I2C BIT(9)
-#define GXBB_GCLK_MPEG_1_ETH BIT(3)
-
-#endif /* __GXBB_H__ */
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
#define ATMEL_PIO_OPD_MASK BIT(14)
#define ATMEL_PIO_SCHMITT_MASK BIT(15)
+#define ATMEL_PIO_DRVSTR_MASK GENMASK(17, 16)
+#define ATMEL_PIO_DRVSTR_LO (1 << 16)
+#define ATMEL_PIO_DRVSTR_ME (2 << 16)
+#define ATMEL_PIO_DRVSTR_HI (3 << 16)
#define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24)
#define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24)
#define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24)
#define AT91_PIO_PORTC 0x2
#define AT91_PIO_PORTD 0x3
-int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup);
-int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup);
+int atmel_pio4_set_gpio(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 config);
+int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 config);
int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value);
int atmel_pio4_get_pio_input(u32 port, u32 pin);
#include <common.h>
#include <linux/libfdt.h>
#include <linux/err.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <asm/arch/sm.h>
#include <asm/armv8/mmu.h>
#include <asm/unaligned.h>
phys_size_t get_effective_memsize(void)
{
/* Size is reported in MiB, convert it in bytes */
- return ((readl(GXBB_AO_SEC_GP_CFG0) & GXBB_AO_MEM_SIZE_MASK)
- >> GXBB_AO_MEM_SIZE_SHIFT) * SZ_1M;
+ return ((readl(GX_AO_SEC_GP_CFG0) & GX_AO_MEM_SIZE_MASK)
+ >> GX_AO_MEM_SIZE_SHIFT) * SZ_1M;
}
static void meson_board_add_reserved_memory(void *fdt, u64 start, u64 size)
* - AO_SEC_GP_CFG4: bl32 physical start address, can be NULL
*/
- reg = readl(GXBB_AO_SEC_GP_CFG3);
+ reg = readl(GX_AO_SEC_GP_CFG3);
- bl31_size = ((reg & GXBB_AO_BL31_RSVMEM_SIZE_MASK)
- >> GXBB_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
- bl32_size = (reg & GXBB_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
+ bl31_size = ((reg & GX_AO_BL31_RSVMEM_SIZE_MASK)
+ >> GX_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
+ bl32_size = (reg & GX_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
- bl31_start = readl(GXBB_AO_SEC_GP_CFG5);
- bl32_start = readl(GXBB_AO_SEC_GP_CFG4);
+ bl31_start = readl(GX_AO_SEC_GP_CFG5);
+ bl32_start = readl(GX_AO_SEC_GP_CFG4);
/*
- * Early Meson GXBB Firmware revisions did not provide the reserved
+ * Early Meson GX Firmware revisions did not provide the reserved
* memory zones in the registers, keep fixed memory zone handling.
*/
- if (IS_ENABLED(CONFIG_MESON_GXBB) &&
+ if (IS_ENABLED(CONFIG_MESON_GX) &&
!reg && !bl31_start && !bl32_start) {
bl31_start = 0x10000000;
bl31_size = 0x200000;
}
/* Add first 16MiB reserved zone */
- meson_board_add_reserved_memory(fdt, 0, GXBB_FIRMWARE_MEM_SIZE);
+ meson_board_add_reserved_memory(fdt, 0, GX_FIRMWARE_MEM_SIZE);
/* Add BL31 reserved zone */
if (bl31_start && bl31_size)
psci_system_reset();
}
-static struct mm_region gxbb_mem_map[] = {
+static struct mm_region gx_mem_map[] = {
{
.virt = 0x0UL,
.phys = 0x0UL,
}
};
-struct mm_region *mem_map = gxbb_mem_map;
+struct mm_region *mem_map = gx_mem_map;
#include <common.h>
#include <dm.h>
#include <asm/io.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <asm/arch/eth.h>
#include <phy.h>
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
/* Set RGMII mode */
- setbits_le32(GXBB_ETH_REG_0, GXBB_ETH_REG_0_PHY_INTF |
- GXBB_ETH_REG_0_TX_PHASE(1) |
- GXBB_ETH_REG_0_TX_RATIO(4) |
- GXBB_ETH_REG_0_PHY_CLK_EN |
- GXBB_ETH_REG_0_CLK_EN);
+ setbits_le32(GX_ETH_REG_0, GX_ETH_REG_0_PHY_INTF |
+ GX_ETH_REG_0_TX_PHASE(1) |
+ GX_ETH_REG_0_TX_RATIO(4) |
+ GX_ETH_REG_0_PHY_CLK_EN |
+ GX_ETH_REG_0_CLK_EN);
break;
case PHY_INTERFACE_MODE_RMII:
/* Set RMII mode */
- out_le32(GXBB_ETH_REG_0, GXBB_ETH_REG_0_INVERT_RMII_CLK |
- GXBB_ETH_REG_0_CLK_EN);
+ out_le32(GX_ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK |
+ GX_ETH_REG_0_CLK_EN);
/* Use GXL RMII Internal PHY */
if (IS_ENABLED(CONFIG_MESON_GXL) &&
(flags & MESON_GXL_USE_INTERNAL_RMII_PHY)) {
- writel(0x10110181, GXBB_ETH_REG_2);
- writel(0xe40908ff, GXBB_ETH_REG_3);
+ writel(0x10110181, GX_ETH_REG_2);
+ writel(0xe40908ff, GX_ETH_REG_3);
}
break;
}
/* Enable power and clock gate */
- setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH);
- clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
+ setbits_le32(GX_GCLK_MPEG_1, GX_GCLK_MPEG_1_ETH);
+ clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
}
*/
#include <common.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <linux/kernel.h>
#define FN_GET_SHARE_MEM_INPUT_BASE 0x82000020
switch (cpu_rev) {
case DRA762_ES1_0:
+ case DRA762_ABZ_ES1_0:
+ case DRA762_ACD_ES1_0:
cpu = "DRA762";
break;
case DRA752_ES1_0:
obj-$(CONFIG_SPL_BUILD) += spl.o
obj-$(CONFIG_ARMV7_PSCI) += psci.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o
enum {
STM32MP_SYSCON_UNKNOWN,
STM32MP_SYSCON_STGEN,
+ STM32MP_SYSCON_PWR,
};
/*
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#define STM32MP_PWR_CR3 0xc
+#define STM32MP_PWR_CR3_USB33DEN BIT(24)
+#define STM32MP_PWR_CR3_USB33RDY BIT(26)
+#define STM32MP_PWR_CR3_REG18DEN BIT(28)
+#define STM32MP_PWR_CR3_REG18RDY BIT(29)
+#define STM32MP_PWR_CR3_REG11DEN BIT(30)
+#define STM32MP_PWR_CR3_REG11RDY BIT(31)
+
+struct stm32mp_pwr_reg_info {
+ u32 enable;
+ u32 ready;
+ char *name;
+};
+
+struct stm32mp_pwr_priv {
+ struct regmap *regmap;
+};
+
+static int stm32mp_pwr_write(struct udevice *dev, uint reg,
+ const uint8_t *buff, int len)
+{
+ struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
+ u32 val = *(u32 *)buff;
+
+ if (len != 4)
+ return -EINVAL;
+
+ return regmap_write(priv->regmap, STM32MP_PWR_CR3, val);
+}
+
+static int stm32mp_pwr_read(struct udevice *dev, uint reg, uint8_t *buff,
+ int len)
+{
+ struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
+
+ if (len != 4)
+ return -EINVAL;
+
+ return regmap_read(priv->regmap, STM32MP_PWR_CR3, (u32 *)buff);
+}
+
+static int stm32mp_pwr_ofdata_to_platdata(struct udevice *dev)
+{
+ struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
+ struct regmap *regmap;
+
+ regmap = syscon_get_regmap_by_driver_data(STM32MP_SYSCON_PWR);
+ if (IS_ERR(regmap)) {
+ pr_err("%s: unable to find regmap (%ld)\n", __func__,
+ PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+ priv->regmap = regmap;
+
+ return 0;
+}
+
+static const struct pmic_child_info pwr_children_info[] = {
+ { .prefix = "reg", .driver = "stm32mp_pwr_regulator"},
+ { .prefix = "usb", .driver = "stm32mp_pwr_regulator"},
+ { },
+};
+
+static int stm32mp_pwr_bind(struct udevice *dev)
+{
+ int children;
+
+ children = pmic_bind_children(dev, dev->node, pwr_children_info);
+ if (!children)
+ dev_dbg(dev, "no child found\n");
+
+ return 0;
+}
+
+static struct dm_pmic_ops stm32mp_pwr_ops = {
+ .read = stm32mp_pwr_read,
+ .write = stm32mp_pwr_write,
+};
+
+static const struct udevice_id stm32mp_pwr_ids[] = {
+ { .compatible = "st,stm32mp1,pwr-reg" },
+ { }
+};
+
+U_BOOT_DRIVER(stm32mp_pwr_pmic) = {
+ .name = "stm32mp_pwr_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = stm32mp_pwr_ids,
+ .bind = stm32mp_pwr_bind,
+ .ops = &stm32mp_pwr_ops,
+ .ofdata_to_platdata = stm32mp_pwr_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct stm32mp_pwr_priv),
+};
+
+static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg11 = {
+ .enable = STM32MP_PWR_CR3_REG11DEN,
+ .ready = STM32MP_PWR_CR3_REG11RDY,
+ .name = "reg11"
+};
+
+static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg18 = {
+ .enable = STM32MP_PWR_CR3_REG18DEN,
+ .ready = STM32MP_PWR_CR3_REG18RDY,
+ .name = "reg18"
+};
+
+static const struct stm32mp_pwr_reg_info stm32mp_pwr_usb33 = {
+ .enable = STM32MP_PWR_CR3_USB33DEN,
+ .ready = STM32MP_PWR_CR3_USB33RDY,
+ .name = "usb33"
+};
+
+static const struct stm32mp_pwr_reg_info *stm32mp_pwr_reg_infos[] = {
+ &stm32mp_pwr_reg11,
+ &stm32mp_pwr_reg18,
+ &stm32mp_pwr_usb33,
+ NULL
+};
+
+static int stm32mp_pwr_regulator_probe(struct udevice *dev)
+{
+ const struct stm32mp_pwr_reg_info **p = stm32mp_pwr_reg_infos;
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ while (*p) {
+ int rc;
+
+ rc = dev_read_stringlist_search(dev, "regulator-name",
+ (*p)->name);
+ if (rc >= 0) {
+ dev_dbg(dev, "found regulator %s\n", (*p)->name);
+ break;
+ } else if (rc != -ENODATA) {
+ return rc;
+ }
+ p++;
+ }
+ if (!*p) {
+ int i = 0;
+ const char *s;
+
+ dev_dbg(dev, "regulator ");
+ while (dev_read_string_index(dev, "regulator-name",
+ i++, &s) >= 0)
+ dev_dbg(dev, "%s'%s' ", (i > 1) ? ", " : "", s);
+ dev_dbg(dev, "%s not supported\n", (i > 2) ? "are" : "is");
+ return -EINVAL;
+ }
+
+ uc_pdata->type = REGULATOR_TYPE_FIXED;
+ dev->priv = (void *)*p;
+
+ return 0;
+}
+
+static int stm32mp_pwr_regulator_set_value(struct udevice *dev, int uV)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ if (!uc_pdata)
+ return -ENXIO;
+
+ if (uc_pdata->min_uV != uV) {
+ dev_dbg(dev, "Invalid uV=%d for: %s\n", uV, uc_pdata->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stm32mp_pwr_regulator_get_value(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ if (!uc_pdata)
+ return -ENXIO;
+
+ if (uc_pdata->min_uV != uc_pdata->max_uV) {
+ dev_dbg(dev, "Invalid constraints for: %s\n", uc_pdata->name);
+ return -EINVAL;
+ }
+
+ return uc_pdata->min_uV;
+}
+
+static int stm32mp_pwr_regulator_get_enable(struct udevice *dev)
+{
+ const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
+ int rc;
+ u32 reg;
+
+ rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg));
+ if (rc)
+ return rc;
+
+ dev_dbg(dev, "%s id %s\n", p->name, (reg & p->enable) ? "on" : "off");
+
+ return (reg & p->enable) != 0;
+}
+
+static int stm32mp_pwr_regulator_set_enable(struct udevice *dev, bool enable)
+{
+ const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
+ int rc;
+ u32 reg;
+ u32 time_start;
+
+ dev_dbg(dev, "Turning %s %s\n", enable ? "on" : "off", p->name);
+
+ rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg));
+ if (rc)
+ return rc;
+
+ /* if regulator is already in the wanted state, nothing to do */
+ if (!!(reg & p->enable) == enable)
+ return 0;
+
+ reg &= ~p->enable;
+ if (enable)
+ reg |= p->enable;
+
+ rc = pmic_write(dev->parent, 0, (uint8_t *)®, sizeof(reg));
+ if (rc)
+ return rc;
+
+ if (!enable)
+ return 0;
+
+ /* waiting ready for enable */
+ time_start = get_timer(0);
+ while (1) {
+ rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg));
+ if (rc)
+ return rc;
+ if (reg & p->ready)
+ break;
+ if (get_timer(time_start) > CONFIG_SYS_HZ) {
+ dev_dbg(dev, "%s: timeout\n", p->name);
+ return -ETIMEDOUT;
+ }
+ }
+ return 0;
+}
+
+static const struct dm_regulator_ops stm32mp_pwr_regulator_ops = {
+ .set_value = stm32mp_pwr_regulator_set_value,
+ .get_value = stm32mp_pwr_regulator_get_value,
+ .get_enable = stm32mp_pwr_regulator_get_enable,
+ .set_enable = stm32mp_pwr_regulator_set_enable,
+};
+
+U_BOOT_DRIVER(stm32mp_pwr_regulator) = {
+ .name = "stm32mp_pwr_regulator",
+ .id = UCLASS_REGULATOR,
+ .ops = &stm32mp_pwr_regulator_ops,
+ .probe = stm32mp_pwr_regulator_probe,
+};
static const struct udevice_id stm32mp_syscon_ids[] = {
{ .compatible = "st,stm32-stgen",
.data = STM32MP_SYSCON_STGEN },
+ { .compatible = "st,stm32mp1-pwr",
+ .data = STM32MP_SYSCON_PWR },
{ }
};
gpios = <&gpio_a 2 0>;
label = "sandbox:green";
};
+
+ default_on {
+ gpios = <&gpio_a 5 0>;
+ label = "sandbox:default_on";
+ default-state = "on";
+ };
+
+ default_off {
+ gpios = <&gpio_a 6 0>;
+ label = "sandbox:default_off";
+ default-state = "off";
+ };
};
mbox: mbox {
#include <dm.h>
#include <environment.h>
#include <asm/io.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <asm/arch/mem.h>
#include <asm/arch/sm.h>
#include <asm/arch/eth.h>
#include <dm.h>
#include <environment.h>
#include <asm/io.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <asm/arch/sm.h>
#include <asm/arch/eth.h>
#include <asm/arch/mem.h>
MESON_GXL_USE_INTERNAL_RMII_PHY);
/* Enable power and clock gate */
- setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH);
- clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
+ setbits_le32(GX_GCLK_MPEG_1, GX_GCLK_MPEG_1_ETH);
+ clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
#include <dm.h>
#include <environment.h>
#include <asm/io.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <asm/arch/sm.h>
#include <asm/arch/eth.h>
#include <asm/arch/mem.h>
meson_gx_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
/* Enable power and clock gate */
- setbits_le32(GXBB_GCLK_MPEG_0, GXBB_GCLK_MPEG_0_I2C);
+ setbits_le32(GX_GCLK_MPEG_0, GX_GCLK_MPEG_0_I2C);
/* Reset PHY on GPIOZ_14 */
- clrbits_le32(GXBB_GPIO_EN(3), BIT(14));
- clrbits_le32(GXBB_GPIO_OUT(3), BIT(14));
+ clrbits_le32(GX_GPIO_EN(3), BIT(14));
+ clrbits_le32(GX_GPIO_OUT(3), BIT(14));
mdelay(10);
- setbits_le32(GXBB_GPIO_OUT(3), BIT(14));
+ setbits_le32(GX_GPIO_OUT(3), BIT(14));
if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
#include <dm.h>
#include <environment.h>
#include <asm/io.h>
-#include <asm/arch/gxbb.h>
+#include <asm/arch/gx.h>
#include <asm/arch/sm.h>
#include <asm/arch/eth.h>
#include <asm/arch/mem.h>
static void board_usb_hw_init(void)
{
- atmel_pio4_set_pio_output(AT91_PIO_PORTB, 10, 1);
+ atmel_pio4_set_pio_output(AT91_PIO_PORTA, 27, 1);
}
#ifdef CONFIG_BOARD_LATE_INIT
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
static void board_uart1_hw_init(void)
{
- atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, 1); /* URXD1 */
+ atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, ATMEL_PIO_PUEN_MASK); /* URXD1 */
atmel_pio4_set_a_periph(AT91_PIO_PORTD, 3, 0); /* UTXD1 */
at91_periph_clk_enable(ATMEL_ID_UART1);
writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(1) |
AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(1),
&smc->cs[3].setup);
- writel(AT91_SMC_PULSE_NWE(2) | AT91_SMC_PULSE_NCS_WR(3) |
+ writel(AT91_SMC_PULSE_NWE(2) | AT91_SMC_PULSE_NCS_WR(4) |
AT91_SMC_PULSE_NRD(2) | AT91_SMC_PULSE_NCS_RD(3),
&smc->cs[3].pulse);
- writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(5),
+ writel(AT91_SMC_CYCLE_NWE(6) | AT91_SMC_CYCLE_NRD(5),
&smc->cs[3].cycle);
writel(AT91_SMC_TIMINGS_TCLR(2) | AT91_SMC_TIMINGS_TADL(7) |
AT91_SMC_TIMINGS_TAR(2) | AT91_SMC_TIMINGS_TRR(3) |
AT91_SMC_MODE_TDF_CYCLE(3),
&smc->cs[3].mode);
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 22, 0); /* D0 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 23, 0); /* D1 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 24, 0); /* D2 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 25, 0); /* D3 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 26, 0); /* D4 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 27, 0); /* D5 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 28, 0); /* D6 */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 29, 0); /* D7 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 22, ATMEL_PIO_DRVSTR_ME); /* D0 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 23, ATMEL_PIO_DRVSTR_ME); /* D1 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 24, ATMEL_PIO_DRVSTR_ME); /* D2 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 25, ATMEL_PIO_DRVSTR_ME); /* D3 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 26, ATMEL_PIO_DRVSTR_ME); /* D4 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 27, ATMEL_PIO_DRVSTR_ME); /* D5 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 28, ATMEL_PIO_DRVSTR_ME); /* D6 */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 29, ATMEL_PIO_DRVSTR_ME); /* D7 */
atmel_pio4_set_b_periph(AT91_PIO_PORTB, 2, 0); /* RE */
atmel_pio4_set_b_periph(AT91_PIO_PORTA, 30, 0); /* WE */
- atmel_pio4_set_b_periph(AT91_PIO_PORTA, 31, 1); /* NCS */
- atmel_pio4_set_b_periph(AT91_PIO_PORTC, 8, 1); /* RDY */
- atmel_pio4_set_b_periph(AT91_PIO_PORTB, 0, 1); /* ALE */
- atmel_pio4_set_b_periph(AT91_PIO_PORTB, 1, 1); /* CLE */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTA, 31, ATMEL_PIO_PUEN_MASK); /* NCS */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTC, 8, ATMEL_PIO_PUEN_MASK); /* RDY */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTB, 0, ATMEL_PIO_PUEN_MASK); /* ALE */
+ atmel_pio4_set_b_periph(AT91_PIO_PORTB, 1, ATMEL_PIO_PUEN_MASK); /* CLE */
}
#endif
static void board_usb_hw_init(void)
{
- atmel_pio4_set_pio_output(AT91_PIO_PORTB, 12, 1);
+ atmel_pio4_set_pio_output(AT91_PIO_PORTB, 12, ATMEL_PIO_PUEN_MASK);
}
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
static void board_uart0_hw_init(void)
{
- atmel_pio4_set_c_periph(AT91_PIO_PORTB, 26, 1); /* URXD0 */
+ atmel_pio4_set_c_periph(AT91_PIO_PORTB, 26, ATMEL_PIO_PUEN_MASK); /* URXD0 */
atmel_pio4_set_c_periph(AT91_PIO_PORTB, 27, 0); /* UTXD0 */
at91_periph_clk_enable(ATMEL_ID_UART0);
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
static void board_uart1_hw_init(void)
{
- atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, 1); /* URXD1 */
+ atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, ATMEL_PIO_PUEN_MASK); /* URXD1 */
atmel_pio4_set_a_periph(AT91_PIO_PORTD, 3, 0); /* UTXD1 */
at91_periph_clk_enable(ATMEL_ID_UART1);
saved to memory or to an environment variable. It is also possible
to verify a hash against data in memory.
+config CMD_HVC
+ bool "Support the 'hvc' command"
+ depends on ARM_SMCCC
+ help
+ Allows issuing Hypervisor Calls (HVCs). Mostly useful for
+ development and testing.
+
+config CMD_SMC
+ bool "Support the 'smc' command"
+ depends on ARM_SMCCC
+ help
+ Allows issuing Secure Monitor Calls (SMCs). Mostly useful for
+ development and testing.
+
config HASH_VERIFY
bool "hash -v"
depends on CMD_HASH
obj-$(CONFIG_CMD_FUSE) += fuse.o
obj-$(CONFIG_CMD_GETTIME) += gettime.o
obj-$(CONFIG_CMD_GPIO) += gpio.o
+obj-$(CONFIG_CMD_HVC) += smccc.o
obj-$(CONFIG_CMD_I2C) += i2c.o
obj-$(CONFIG_CMD_IOTRACE) += iotrace.o
obj-$(CONFIG_CMD_HASH) += hash.o
obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
obj-$(CONFIG_CMD_SPI) += spi.o
obj-$(CONFIG_CMD_STRINGS) += strings.o
+obj-$(CONFIG_CMD_SMC) += smccc.o
obj-$(CONFIG_CMD_TERMINAL) += terminal.o
obj-$(CONFIG_CMD_TIME) += time.o
obj-$(CONFIG_CMD_TRACE) += trace.o
#include <command.h>
#include <console.h>
#include <mmc.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
static int curr_device = -1;
}
#if CONFIG_IS_ENABLED(MMC_WRITE)
+#if defined(CONFIG_FASTBOOT_FLASH)
+static lbaint_t mmc_sparse_write(struct sparse_storage *info, lbaint_t blk,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct blk_desc *dev_desc = info->priv;
+
+ return blk_dwrite(dev_desc, blk, blkcnt, buffer);
+}
+
+static lbaint_t mmc_sparse_reserve(struct sparse_storage *info,
+ lbaint_t blk, lbaint_t blkcnt)
+{
+ return blkcnt;
+}
+
+static int do_mmc_sparse_write(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct sparse_storage sparse;
+ struct blk_desc *dev_desc;
+ struct mmc *mmc;
+ char dest[11];
+ void *addr;
+ u32 blk;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+
+ if (!is_sparse_image(addr)) {
+ printf("Not a sparse image\n");
+ return CMD_RET_FAILURE;
+ }
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC Sparse write: dev # %d, block # %d ... ",
+ curr_device, blk);
+
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ dev_desc = mmc_get_blk_desc(mmc);
+ sparse.priv = dev_desc;
+ sparse.blksz = 512;
+ sparse.start = blk;
+ sparse.size = dev_desc->lba - blk;
+ sparse.write = mmc_sparse_write;
+ sparse.reserve = mmc_sparse_reserve;
+ sparse.mssg = NULL;
+ sprintf(dest, "0x" LBAF, sparse.start * sparse.blksz);
+
+ if (write_sparse_image(&sparse, dest, addr))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+#endif
+
static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
{
U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
#if CONFIG_IS_ENABLED(MMC_WRITE)
U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
+#if defined(CONFIG_FASTBOOT_FLASH)
+ U_BOOT_CMD_MKENT(swrite, 3, 0, do_mmc_sparse_write, "", ""),
+#endif
U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
#endif
U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
"info - display info of the current MMC device\n"
"mmc read addr blk# cnt\n"
"mmc write addr blk# cnt\n"
+#if defined(CONFIG_FASTBOOT_FLASH)
+ "mmc swrite addr blk#\n"
+#endif
"mmc erase blk# cnt\n"
"mmc rescan\n"
"mmc part - lists available partition on current mmc device\n"
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018
+ * Michalis Pappas <mpappas@fastmail.fm>
+ */
+#include <asm/psci.h>
+#include <common.h>
+#include <command.h>
+#include <linux/arm-smccc.h>
+#include <linux/compiler.h>
+#include <linux/psci.h>
+
+static int do_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct arm_smccc_res res;
+
+ unsigned long fid;
+
+ unsigned long a1;
+ unsigned long a2;
+ unsigned long a3;
+ unsigned long a4;
+ unsigned long a5;
+ unsigned long a6;
+ unsigned long a7;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ fid = simple_strtoul(argv[1], NULL, 16);
+
+ a1 = argc > 2 ? simple_strtoul(argv[2], NULL, 16) : 0;
+ a2 = argc > 3 ? simple_strtoul(argv[3], NULL, 16) : 0;
+ a3 = argc > 4 ? simple_strtoul(argv[4], NULL, 16) : 0;
+ a4 = argc > 5 ? simple_strtoul(argv[5], NULL, 16) : 0;
+ a5 = argc > 6 ? simple_strtoul(argv[6], NULL, 16) : 0;
+ a6 = argc > 7 ? simple_strtoul(argv[7], NULL, 16) : 0;
+ a7 = argc > 8 ? simple_strtoul(argv[8], NULL, 16) : 0;
+
+ if (!strcmp(argv[0], "smc"))
+ arm_smccc_smc(fid, a1, a2, a3, a4, a5, a6, a7, &res);
+ else
+ arm_smccc_hvc(fid, a1, a2, a3, a4, a5, a6, a7, &res);
+
+ printf("Res: %ld %ld %ld %ld\n", res.a0, res.a1, res.a2, res.a3);
+
+ return 0;
+}
+
+#ifdef CONFIG_CMD_SMC
+U_BOOT_CMD(
+ smc, 8, 2, do_call,
+ "Issue a Secure Monitor Call",
+ "<fid> [arg1 ... arg6] [id]\n"
+ " - fid Function ID\n"
+ " - arg SMC arguments, passed to X1-X6 (default to zero)\n"
+ " - id Secure OS ID / Session ID, passed to W7 (defaults to zero)\n"
+);
+#endif
+
+#ifdef CONFIG_CMD_HVC
+U_BOOT_CMD(
+ hvc, 8, 2, do_call,
+ "Issue a Hypervisor Call",
+ "<fid> [arg1...arg7] [id]\n"
+ " - fid Function ID\n"
+ " - arg HVC arguments, passed to X1-X6 (default to zero)\n"
+ " - id Session ID, passed to W7 (defaults to zero)\n"
+);
+#endif
+
if (is_sparse_image(download_buffer)) {
struct fb_mmc_sparse sparse_priv;
struct sparse_storage sparse;
+ int err;
sparse_priv.dev_desc = dev_desc;
sparse.size = info.size;
sparse.write = fb_mmc_sparse_write;
sparse.reserve = fb_mmc_sparse_reserve;
+ sparse.mssg = fastboot_fail;
printf("Flashing sparse image at offset " LBAFU "\n",
sparse.start);
sparse.priv = &sparse_priv;
- write_sparse_image(&sparse, cmd, download_buffer,
- download_bytes);
+ err = write_sparse_image(&sparse, cmd, download_buffer);
+ if (!err)
+ fastboot_okay("");
} else {
write_raw_image(dev_desc, &info, cmd, download_buffer,
download_bytes);
sparse.size = part->size / sparse.blksz;
sparse.write = fb_nand_sparse_write;
sparse.reserve = fb_nand_sparse_reserve;
+ sparse.mssg = fastboot_fail;
printf("Flashing sparse image at offset " LBAFU "\n",
sparse.start);
sparse.priv = &sparse_priv;
- write_sparse_image(&sparse, cmd, download_buffer,
- download_bytes);
+ ret = write_sparse_image(&sparse, cmd, download_buffer);
+ if (!ret)
+ fastboot_okay("");
} else {
printf("Flashing raw image at offset 0x%llx\n",
part->offset);
#include <malloc.h>
#include <part.h>
#include <sparse_format.h>
-#include <fastboot.h>
#include <linux/math64.h>
#define CONFIG_FASTBOOT_FLASH_FILLBUF_SIZE (1024 * 512)
#endif
-void write_sparse_image(
- struct sparse_storage *info, const char *part_name,
- void *data, unsigned sz)
+static void default_log(const char *ignored) {}
+
+int write_sparse_image(struct sparse_storage *info,
+ const char *part_name, void *data)
{
lbaint_t blk;
lbaint_t blkcnt;
data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
}
+ if (!info->mssg)
+ info->mssg = default_log;
+
debug("=== Sparse Image Header ===\n");
debug("magic: 0x%x\n", sparse_header->magic);
debug("major_version: 0x%x\n", sparse_header->major_version);
if (offset) {
printf("%s: Sparse image block size issue [%u]\n",
__func__, sparse_header->blk_sz);
- fastboot_fail("sparse image block size issue");
- return;
+ info->mssg("sparse image block size issue");
+ return -1;
}
puts("Flashing Sparse Image\n");
case CHUNK_TYPE_RAW:
if (chunk_header->total_sz !=
(sparse_header->chunk_hdr_sz + chunk_data_sz)) {
- fastboot_fail(
- "Bogus chunk size for chunk type Raw");
- return;
+ info->mssg("Bogus chunk size for chunk type Raw");
+ return -1;
}
if (blk + blkcnt > info->start + info->size) {
printf(
"%s: Request would exceed partition size!\n",
__func__);
- fastboot_fail(
- "Request would exceed partition size!");
- return;
+ info->mssg("Request would exceed partition size!");
+ return -1;
}
blks = info->write(info, blk, blkcnt, data);
printf("%s: %s" LBAFU " [" LBAFU "]\n",
__func__, "Write failed, block #",
blk, blks);
- fastboot_fail(
- "flash write failure");
- return;
+ info->mssg("flash write failure");
+ return -1;
}
blk += blks;
bytes_written += blkcnt * info->blksz;
case CHUNK_TYPE_FILL:
if (chunk_header->total_sz !=
(sparse_header->chunk_hdr_sz + sizeof(uint32_t))) {
- fastboot_fail(
- "Bogus chunk size for chunk type FILL");
- return;
+ info->mssg("Bogus chunk size for chunk type FILL");
+ return -1;
}
fill_buf = (uint32_t *)
info->blksz * fill_buf_num_blks,
ARCH_DMA_MINALIGN));
if (!fill_buf) {
- fastboot_fail(
- "Malloc failed for: CHUNK_TYPE_FILL");
- return;
+ info->mssg("Malloc failed for: CHUNK_TYPE_FILL");
+ return -1;
}
fill_val = *(uint32_t *)data;
printf(
"%s: Request would exceed partition size!\n",
__func__);
- fastboot_fail(
- "Request would exceed partition size!");
- return;
+ info->mssg("Request would exceed partition size!");
+ return -1;
}
for (i = 0; i < blkcnt;) {
__func__,
"Write failed, block #",
blk, j);
- fastboot_fail(
- "flash write failure");
+ info->mssg("flash write failure");
free(fill_buf);
- return;
+ return -1;
}
blk += blks;
i += j;
case CHUNK_TYPE_CRC32:
if (chunk_header->total_sz !=
sparse_header->chunk_hdr_sz) {
- fastboot_fail(
- "Bogus chunk size for chunk type Dont Care");
- return;
+ info->mssg("Bogus chunk size for chunk type Dont Care");
+ return -1;
}
total_blocks += chunk_header->chunk_sz;
data += chunk_data_sz;
default:
printf("%s: Unknown chunk type: %x\n", __func__,
chunk_header->chunk_type);
- fastboot_fail("Unknown chunk type");
- return;
+ info->mssg("Unknown chunk type");
+ return -1;
}
}
total_blocks, sparse_header->total_blks);
printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name);
- if (total_blocks != sparse_header->total_blks)
- fastboot_fail("sparse image write failure");
- else
- fastboot_okay("");
+ if (total_blocks != sparse_header->total_blks) {
+ info->mssg("sparse image write failure");
+ return -1;
+ }
- return;
+ return 0;
}
CONFIG_DEBUG_UART=y
CONFIG_ENV_VARS_UBOOT_CONFIG=y
CONFIG_FIT=y
-CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_MMC"
+CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2"
CONFIG_SD_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_CONSOLE_MUX=y
CONFIG_DEBUG_UART=y
CONFIG_ENV_VARS_UBOOT_CONFIG=y
CONFIG_FIT=y
-CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_NANDFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2"
CONFIG_NAND_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_CONSOLE_MUX=y
CONFIG_NAND_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_CONSOLE_MUX is not set
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPI_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_CONSOLE_MUX is not set
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_NAND_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_HUSH_PARSER=y
CONFIG_CMD_BOOTZ=y
CONFIG_NAND_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_CONSOLE_MUX is not set
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPI_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPL_SPI_LOAD=y
CONFIG_HUSH_PARSER=y
CONFIG_NAND_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_HUSH_PARSER=y
CONFIG_CMD_BOOTZ=y
CONFIG_SPI_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPL_SPI_LOAD=y
CONFIG_HUSH_PARSER=y
CONFIG_NAND_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_CONSOLE_MUX is not set
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPI_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,256K(env),256k(env_redundant),256k(spare),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256K(env_redundant),256k(env),512k(dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPL_SPI_LOAD=y
CONFIG_HUSH_PARSER=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT4_WRITE=y
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_DM_I2C=y
CONFIG_STM32_SDMMC2=y
# CONFIG_SPL_PINCTRL_FULL is not set
CONFIG_DM_PMIC=y
+# CONFIG_SPL_PMIC_CHILDREN is not set
CONFIG_PMIC_STPMU1=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_DM_REGULATOR_STM32_VREFBUF=y
+CONFIG_DM_REGULATOR_STPMU1=y
CONFIG_STM32_SERIAL=y
# CONFIG_EFI_LOADER is not set
CONFIG_SMC911X=y
CONFIG_SMC911X_BASE=0x0
CONFIG_SMC911X_32_BIT=y
+CONFIG_PINCONF=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_PSCI=y
CONFIG_USB=y
--- /dev/null
+STM32 VREFBUF - Voltage reference buffer
+
+Some STM32 devices embed a voltage reference buffer which can be used as
+voltage reference for ADCs, DACs and also as voltage reference for external
+components through the dedicated VREF+ pin.
+
+Required properties:
+- compatible: Must be "st,stm32-vrefbuf".
+- reg: Offset and length of VREFBUF register set.
+- clocks: Must contain an entry for peripheral clock.
+
+Optional properties:
+- vdda-supply: Phandle to the parent vdda supply regulator node.
+
+Example:
+ vrefbuf: regulator@58003c00 {
+ compatible = "st,stm32-vrefbuf";
+ reg = <0x58003C00 0x8>;
+ clocks = <&rcc VREF_CK>;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2500000>;
+ vdda-supply = <&vdda>;
+ };
- 16-bit resolution
- single and multi-channel conversion mode
+config SARADC_MESON
+ bool "Enable Amlogic Meson SARADC driver"
+ imply REGMAP
+ help
+ This enables driver for Amlogic Meson SARADC.
+ It provides:
+ - 8 analog input channels
+ - 1O or 12 bits resolution
+ - Up to 1MSPS of sample rate
+
config SARADC_ROCKCHIP
bool "Enable Rockchip SARADC driver"
help
obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
+obj-$(CONFIG_SARADC_MESON) += meson-saradc.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ * Copyright (C) 2018 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Amlogic Meson Successive Approximation Register (SAR) A/D Converter
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <clk.h>
+#include <dm.h>
+#include <regmap.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/math64.h>
+#include <linux/bitfield.h>
+
+#define MESON_SAR_ADC_REG0 0x00
+ #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31)
+ #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28)
+ #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30)
+ #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29)
+ #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28)
+ #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27)
+ #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26)
+ #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21)
+ #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19)
+ #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16)
+ #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15)
+ #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14)
+ #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12)
+ #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10)
+ #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9)
+ #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4)
+ #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3)
+ #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2)
+ #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1)
+ #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0)
+
+#define MESON_SAR_ADC_CHAN_LIST 0x04
+ #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24)
+ #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \
+ (GENMASK(2, 0) << ((_chan) * 3))
+
+#define MESON_SAR_ADC_AVG_CNTL 0x08
+ #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \
+ (16 + ((_chan) * 2))
+ #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \
+ (GENMASK(17, 16) << ((_chan) * 2))
+ #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \
+ (0 + ((_chan) * 2))
+ #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \
+ (GENMASK(1, 0) << ((_chan) * 2))
+
+#define MESON_SAR_ADC_REG3 0x0c
+ #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31)
+ #define MESON_SAR_ADC_REG3_CLK_EN BIT(30)
+ #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28)
+ #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27)
+ #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26)
+ #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23)
+ #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22)
+ #define MESON_SAR_ADC_REG3_ADC_EN BIT(21)
+ #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18)
+ #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16)
+ #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10
+ #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5
+ #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8)
+ #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0)
+
+#define MESON_SAR_ADC_DELAY 0x10
+ #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24)
+ #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15)
+ #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14)
+ #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16)
+ #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8)
+ #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0)
+
+#define MESON_SAR_ADC_LAST_RD 0x14
+ #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16)
+ #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0)
+
+#define MESON_SAR_ADC_FIFO_RD 0x18
+ #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12)
+ #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0)
+
+#define MESON_SAR_ADC_AUX_SW 0x1c
+ #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \
+ (8 + (((_chan) - 2) * 3))
+ #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6)
+ #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5)
+ #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4)
+ #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3)
+ #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2)
+ #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1)
+ #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0)
+
+#define MESON_SAR_ADC_CHAN_10_SW 0x20
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1)
+ #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0)
+
+#define MESON_SAR_ADC_DETECT_IDLE_SW 0x24
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1)
+ #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0)
+
+#define MESON_SAR_ADC_DELTA_10 0x28
+ #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27)
+ #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26)
+ #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16)
+ #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15)
+ #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11
+ #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11)
+ #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10)
+ #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0)
+
+/*
+ * NOTE: registers from here are undocumented (the vendor Linux kernel driver
+ * and u-boot source served as reference). These only seem to be relevant on
+ * GXBB and newer.
+ */
+#define MESON_SAR_ADC_REG11 0x2c
+ #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13)
+
+#define MESON_SAR_ADC_REG13 0x34
+ #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
+
+#define MESON_SAR_ADC_MAX_FIFO_SIZE 32
+#define MESON_SAR_ADC_TIMEOUT 100 /* ms */
+
+#define NUM_CHANNELS 8
+
+#define MILLION 1000000
+
+struct meson_saradc_data {
+ int num_bits;
+};
+
+struct meson_saradc_priv {
+ const struct meson_saradc_data *data;
+ struct regmap *regmap;
+ struct clk core_clk;
+ struct clk adc_clk;
+ bool initialized;
+ int active_channel;
+ int calibbias;
+ int calibscale;
+};
+
+static unsigned int
+meson_saradc_get_fifo_count(struct meson_saradc_priv *priv)
+{
+ u32 regval;
+
+ regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val);
+
+ return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
+}
+
+static int meson_saradc_lock(struct meson_saradc_priv *priv)
+{
+ uint val, timeout = 10000;
+
+ /* prevent BL30 from using the SAR ADC while we are using it */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY);
+
+ /*
+ * wait until BL30 releases it's lock (so we can use the SAR ADC)
+ */
+ do {
+ udelay(1);
+ regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val);
+ } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--);
+
+ if (timeout < 0) {
+ printf("Timeout while waiting for BL30 unlock\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void meson_saradc_unlock(struct meson_saradc_priv *priv)
+{
+ /* allow BL30 to use the SAR ADC again */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
+}
+
+static void meson_saradc_clear_fifo(struct meson_saradc_priv *priv)
+{
+ unsigned int count, tmp;
+
+ for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) {
+ if (!meson_saradc_get_fifo_count(priv))
+ break;
+
+ regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp);
+ }
+}
+
+static int meson_saradc_calib_val(struct meson_saradc_priv *priv, int val)
+{
+ int tmp;
+
+ /* use val_calib = scale * val_raw + offset calibration function */
+ tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
+
+ return clamp(tmp, 0, (1 << priv->data->num_bits) - 1);
+}
+
+static int meson_saradc_wait_busy_clear(struct meson_saradc_priv *priv)
+{
+ uint regval, timeout = 10000;
+
+ /*
+ * NOTE: we need a small delay before reading the status, otherwise
+ * the sample engine may not have started internally (which would
+ * seem to us that sampling is already finished).
+ */
+ do {
+ udelay(1);
+ regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val);
+ } while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--);
+
+ if (timeout < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int meson_saradc_read_raw_sample(struct meson_saradc_priv *priv,
+ unsigned int channel, uint *val)
+{
+ uint regval, fifo_chan, fifo_val, count;
+ int ret;
+
+ ret = meson_saradc_wait_busy_clear(priv);
+ if (ret)
+ return ret;
+
+ count = meson_saradc_get_fifo_count(priv);
+ if (count != 1) {
+ printf("ADC FIFO has %d element(s) instead of one\n", count);
+ return -EINVAL;
+ }
+
+ regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val);
+ fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
+ if (fifo_chan != channel) {
+ printf("ADC FIFO entry belongs to channel %d instead of %d\n",
+ fifo_chan, channel);
+ return -EINVAL;
+ }
+
+ fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
+ fifo_val &= GENMASK(priv->data->num_bits - 1, 0);
+ *val = meson_saradc_calib_val(priv, fifo_val);
+
+ return 0;
+}
+
+static void meson_saradc_start_sample_engine(struct meson_saradc_priv *priv)
+{
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
+ MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
+ MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLING_START,
+ MESON_SAR_ADC_REG0_SAMPLING_START);
+}
+
+static void meson_saradc_stop_sample_engine(struct meson_saradc_priv *priv)
+{
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLING_STOP,
+ MESON_SAR_ADC_REG0_SAMPLING_STOP);
+
+ /* wait until all modules are stopped */
+ meson_saradc_wait_busy_clear(priv);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0);
+}
+
+enum meson_saradc_avg_mode {
+ NO_AVERAGING = 0x0,
+ MEAN_AVERAGING = 0x1,
+ MEDIAN_AVERAGING = 0x2,
+};
+
+enum meson_saradc_num_samples {
+ ONE_SAMPLE = 0x0,
+ TWO_SAMPLES = 0x1,
+ FOUR_SAMPLES = 0x2,
+ EIGHT_SAMPLES = 0x3,
+};
+
+static void meson_saradc_set_averaging(struct meson_saradc_priv *priv,
+ unsigned int channel,
+ enum meson_saradc_avg_mode mode,
+ enum meson_saradc_num_samples samples)
+{
+ int val;
+
+ val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
+ MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel),
+ val);
+
+ val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
+ MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val);
+}
+
+static void meson_saradc_enable_channel(struct meson_saradc_priv *priv,
+ unsigned int channel)
+{
+ uint regval;
+
+ /*
+ * the SAR ADC engine allows sampling multiple channels at the same
+ * time. to keep it simple we're only working with one *internal*
+ * channel, which starts counting at index 0 (which means: count = 1).
+ */
+ regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
+ MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval);
+
+ /* map channel index 0 to the channel which we want to read */
+ regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), channel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
+ MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval);
+
+ regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
+ channel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
+ MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
+ regval);
+
+ regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
+ channel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
+ MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
+ regval);
+
+ if (channel == 6)
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
+ MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0);
+}
+
+static int meson_saradc_get_sample(struct meson_saradc_priv *priv,
+ int chan, uint *val)
+{
+ int ret;
+
+ ret = meson_saradc_lock(priv);
+ if (ret)
+ return ret;
+
+ /* clear the FIFO to make sure we're not reading old values */
+ meson_saradc_clear_fifo(priv);
+
+ meson_saradc_set_averaging(priv, chan, MEAN_AVERAGING, EIGHT_SAMPLES);
+
+ meson_saradc_enable_channel(priv, chan);
+
+ meson_saradc_start_sample_engine(priv);
+ ret = meson_saradc_read_raw_sample(priv, chan, val);
+ meson_saradc_stop_sample_engine(priv);
+
+ meson_saradc_unlock(priv);
+
+ if (ret) {
+ printf("failed to read sample for channel %d: %d\n",
+ chan, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_saradc_channel_data(struct udevice *dev, int channel,
+ unsigned int *data)
+{
+ struct meson_saradc_priv *priv = dev_get_priv(dev);
+
+ if (channel != priv->active_channel) {
+ pr_err("Requested channel is not active!");
+ return -EINVAL;
+ }
+
+ return meson_saradc_get_sample(priv, channel, data);
+}
+
+enum meson_saradc_chan7_mux_sel {
+ CHAN7_MUX_VSS = 0x0,
+ CHAN7_MUX_VDD_DIV4 = 0x1,
+ CHAN7_MUX_VDD_DIV2 = 0x2,
+ CHAN7_MUX_VDD_MUL3_DIV4 = 0x3,
+ CHAN7_MUX_VDD = 0x4,
+ CHAN7_MUX_CH7_INPUT = 0x7,
+};
+
+static void meson_saradc_set_chan7_mux(struct meson_saradc_priv *priv,
+ enum meson_saradc_chan7_mux_sel sel)
+{
+ u32 regval;
+
+ regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
+
+ udelay(20);
+}
+
+static int meson_saradc_calib(struct meson_saradc_priv *priv)
+{
+ uint nominal0, nominal1, value0, value1;
+ int ret;
+
+ /* use points 25% and 75% for calibration */
+ nominal0 = (1 << priv->data->num_bits) / 4;
+ nominal1 = (1 << priv->data->num_bits) * 3 / 4;
+
+ meson_saradc_set_chan7_mux(priv, CHAN7_MUX_VDD_DIV4);
+ udelay(20);
+ ret = meson_saradc_get_sample(priv, 7, &value0);
+ if (ret < 0)
+ goto out;
+
+ meson_saradc_set_chan7_mux(priv, CHAN7_MUX_VDD_MUL3_DIV4);
+ udelay(20);
+ ret = meson_saradc_get_sample(priv, 7, &value1);
+ if (ret < 0)
+ goto out;
+
+ if (value1 <= value0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION,
+ value1 - value0);
+ priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale,
+ MILLION);
+ ret = 0;
+out:
+ meson_saradc_set_chan7_mux(priv, CHAN7_MUX_CH7_INPUT);
+
+ return ret;
+}
+
+static int meson_saradc_init(struct meson_saradc_priv *priv)
+{
+ uint regval;
+ int ret, i;
+
+ priv->calibscale = MILLION;
+
+ /*
+ * make sure we start at CH7 input since the other muxes are only used
+ * for internal calibration.
+ */
+ meson_saradc_set_chan7_mux(priv, CHAN7_MUX_CH7_INPUT);
+
+ /*
+ * leave sampling delay and the input clocks as configured by
+ * BL30 to make sure BL30 gets the values it expects when
+ * reading the temperature sensor.
+ */
+ regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val);
+ if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED)
+ return 0;
+
+ meson_saradc_stop_sample_engine(priv);
+
+ /* update the channel 6 MUX to select the temperature sensor */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL,
+ MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL);
+
+ /* disable all channels by default */
+ regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY,
+ MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY);
+
+ /* delay between two samples = (10+1) * 1uS */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
+ FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK,
+ 10));
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
+ FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
+ 0));
+
+ /* delay between two samples = (10+1) * 1uS */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
+ FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
+ 10));
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
+ FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
+ 1));
+
+ /*
+ * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW
+ * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1)
+ */
+ regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+ MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK,
+ regval);
+ regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+ MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK,
+ regval);
+
+ /*
+ * set up the input channel muxes in MESON_SAR_ADC_AUX_SW
+ * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable
+ * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and
+ * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver.
+ */
+ regval = 0;
+ for (i = 2; i <= 7; i++)
+ regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i);
+ regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW;
+ regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW;
+ regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval);
+
+ ret = meson_saradc_lock(priv);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable(&priv->core_clk);
+ if (ret)
+ return ret;
+#endif
+
+ regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
+ MESON_SAR_ADC_REG11_BANDGAP_EN,
+ MESON_SAR_ADC_REG11_BANDGAP_EN);
+
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_ADC_EN,
+ MESON_SAR_ADC_REG3_ADC_EN);
+
+ udelay(5);
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable(&priv->adc_clk);
+ if (ret)
+ return ret;
+#endif
+
+ meson_saradc_unlock(priv);
+
+ ret = meson_saradc_calib(priv);
+ if (ret) {
+ printf("calibration failed\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int meson_saradc_start_channel(struct udevice *dev, int channel)
+{
+ struct meson_saradc_priv *priv = dev_get_priv(dev);
+
+ if (channel < 0 || channel >= NUM_CHANNELS) {
+ printf("Requested channel is invalid!");
+ return -EINVAL;
+ }
+
+ if (!priv->initialized) {
+ int ret;
+
+ ret = meson_saradc_init(priv);
+ if (ret)
+ return ret;
+
+ priv->initialized = true;
+ }
+
+ priv->active_channel = channel;
+
+ return 0;
+}
+
+static int meson_saradc_stop(struct udevice *dev)
+{
+ struct meson_saradc_priv *priv = dev_get_priv(dev);
+
+ priv->active_channel = -1;
+
+ return 0;
+}
+
+static int meson_saradc_probe(struct udevice *dev)
+{
+ struct meson_saradc_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = regmap_init_mem(dev, &priv->regmap);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_get_by_name(dev, "core", &priv->core_clk);
+ if (ret)
+ return ret;
+
+ ret = clk_get_by_name(dev, "adc_clk", &priv->adc_clk);
+ if (ret)
+ return ret;
+#endif
+
+ priv->active_channel = -1;
+
+ return 0;
+}
+
+int meson_saradc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct meson_saradc_priv *priv = dev_get_priv(dev);
+
+ priv->data = (struct meson_saradc_data *)dev_get_driver_data(dev);
+
+ uc_pdata->data_mask = GENMASK(priv->data->num_bits - 1, 0);
+ uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+ uc_pdata->data_timeout_us = MESON_SAR_ADC_TIMEOUT * 1000;
+ uc_pdata->channel_mask = GENMASK(NUM_CHANNELS - 1, 0);
+
+ return 0;
+}
+
+static const struct adc_ops meson_saradc_ops = {
+ .start_channel = meson_saradc_start_channel,
+ .channel_data = meson_saradc_channel_data,
+ .stop = meson_saradc_stop,
+};
+
+static const struct meson_saradc_data gxbb_saradc_data = {
+ .num_bits = 10,
+};
+
+static const struct meson_saradc_data gxl_saradc_data = {
+ .num_bits = 12,
+};
+
+static const struct udevice_id meson_saradc_ids[] = {
+ { .compatible = "amlogic,meson-gxbb-saradc",
+ .data = (ulong)&gxbb_saradc_data },
+ { .compatible = "amlogic,meson-gxl-saradc",
+ .data = (ulong)&gxl_saradc_data },
+ { .compatible = "amlogic,meson-gxm-saradc",
+ .data = (ulong)&gxl_saradc_data },
+ { }
+};
+
+U_BOOT_DRIVER(meson_saradc) = {
+ .name = "meson_saradc",
+ .id = UCLASS_ADC,
+ .of_match = meson_saradc_ids,
+ .ops = &meson_saradc_ops,
+ .probe = meson_saradc_probe,
+ .ofdata_to_platdata = meson_saradc_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct meson_saradc_priv),
+};
struct stm32_pwr_regs *pwr_regs;
struct stm32_clk_info info;
unsigned long hse_rate;
+ bool pllsaip;
};
#ifdef CONFIG_VIDEO_STM32
/* configure SDMMC clock */
if (priv->info.v2) { /*stm32f7 case */
- /* select PLLQ as 48MHz clock source */
- clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
+ if (priv->pllsaip)
+ /* select PLLSAIP as 48MHz clock source */
+ setbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
+ else
+ /* select PLLQ as 48MHz clock source */
+ clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
/* select 48MHz as SDMMC1 clock source */
clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
/* select 48MHz as SDMMC2 clock source */
clrbits_le32(®s->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
} else { /* stm32f4 case */
- /* select PLLQ as 48MHz clock source */
- clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
+ if (priv->pllsaip)
+ /* select PLLSAIP as 48MHz clock source */
+ setbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
+ else
+ /* select PLLQ as 48MHz clock source */
+ clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
/* select 48MHz as SDMMC1 clock source */
clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
}
-#ifdef CONFIG_VIDEO_STM32
/*
- * Configure the SAI PLL to generate LTDC pixel clock
+ * Configure the SAI PLL to generate LTDC pixel clock and
+ * 48 Mhz for SDMMC and USB
*/
+ clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIP_MASK,
+ RCC_PLLSAICFGR_PLLSAIP_4);
clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
RCC_PLLSAICFGR_PLLSAIR_3);
clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIN_MASK,
clrsetbits_le32(®s->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK,
RCC_DCKCFGR_PLLSAIDIVR_2 << RCC_DCKCFGR_PLLSAIDIVR_SHIFT);
-#endif
+
/* Enable the main PLL */
setbits_le32(®s->cr, RCC_CR_PLLON);
while (!(readl(®s->cr) & RCC_CR_PLLRDY))
;
-#ifdef CONFIG_VIDEO_STM32
-/* Enable the SAI PLL */
+ /* Enable the SAI PLL */
setbits_le32(®s->cr, RCC_CR_PLLSAION);
while (!(readl(®s->cr) & RCC_CR_PLLSAIRDY))
;
-#endif
setbits_le32(®s->apb1enr, RCC_APB1ENR_PWREN);
if (priv->info.has_overdrive) {
return -EINVAL;
priv->base = (struct stm32_rcc_regs *)addr;
+ priv->pllsaip = true;
switch (dev_get_driver_data(dev)) {
- case STM32F4:
+ case STM32F42X:
+ priv->pllsaip = false;
+ /* fallback into STM32F469 case */
+ case STM32F469:
memcpy(&priv->info, &stm32f4_clk_info,
sizeof(struct stm32_clk_info));
break;
+
case STM32F7:
memcpy(&priv->info, &stm32f7_clk_info,
sizeof(struct stm32_clk_info));
#define RCC_USBCKSELR 0x91C
#define RCC_MP_APB1ENSETR 0xA00
#define RCC_MP_APB2ENSETR 0XA08
+#define RCC_MP_APB3ENSETR 0xA10
#define RCC_MP_AHB2ENSETR 0xA18
#define RCC_MP_AHB4ENSETR 0xA28
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
+ STM32MP1_CLK_SET_CLR_F(RCC_MP_APB3ENSETR, 13, VREF, _PCLK3),
+
STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
return 0;
}
+
+int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
+{
+ uint reg;
+ int ret;
+
+ ret = regmap_read(map, offset, ®);
+ if (ret)
+ return ret;
+
+ reg &= ~mask;
+
+ return regmap_write(map, offset, reg | val);
+}
}
static int atmel_pio4_config_io_func(u32 port, u32 pin,
- u32 func, u32 use_pullup)
+ u32 func, u32 config)
{
struct atmel_pio4_port *port_base;
u32 reg, mask;
mask = 1 << pin;
reg = func;
- reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0;
+ reg |= config;
writel(mask, &port_base->mskr);
writel(reg, &port_base->cfgr);
return 0;
}
-int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_gpio(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_GPIO,
- use_pullup);
+ config);
}
-int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_A,
- use_pullup);
+ config);
}
-int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_B,
- use_pullup);
+ config);
}
-int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_C,
- use_pullup);
+ config);
}
-int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_D,
- use_pullup);
+ config);
}
-int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_E,
- use_pullup);
+ config);
}
-int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_F,
- use_pullup);
+ config);
}
-int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup)
+int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 config)
{
return atmel_pio4_config_io_func(port, pin,
ATMEL_PIO_CFGR_FUNC_PERIPH_G,
- use_pullup);
+ config);
}
int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value)
#include <led.h>
#include <asm/gpio.h>
#include <dm/lists.h>
+#include <dm/uclass-internal.h>
struct led_gpio_priv {
struct gpio_desc gpio;
{
struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
struct led_gpio_priv *priv = dev_get_priv(dev);
+ const char *default_state;
+ int ret;
/* Ignore the top-level LED node */
if (!uc_plat->label)
return 0;
- return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
+
+ ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
+ if (ret)
+ return ret;
+
+ default_state = dev_read_string(dev, "default-state");
+ if (default_state) {
+ if (!strncmp(default_state, "on", 2))
+ gpio_led_set_state(dev, LEDST_ON);
+ else if (!strncmp(default_state, "off", 3))
+ gpio_led_set_state(dev, LEDST_OFF);
+ }
+ return 0;
}
static int led_gpio_remove(struct udevice *dev)
return ret;
uc_plat = dev_get_uclass_platdata(dev);
uc_plat->label = label;
+
+ if (ofnode_read_bool(node, "default-state")) {
+ struct udevice *devp;
+
+ ret = uclass_get_device_tail(dev, 0, &devp);
+ if (ret)
+ return ret;
+ }
}
return 0;
#include <dm/device-internal.h>
#include <dm/lists.h>
-struct stm32_rcc_clk stm32_rcc_clk_f4 = {
+struct stm32_rcc_clk stm32_rcc_clk_f42x = {
.drv_name = "stm32fx_rcc_clock",
- .soc = STM32F4,
+ .soc = STM32F42X,
+};
+
+struct stm32_rcc_clk stm32_rcc_clk_f469 = {
+ .drv_name = "stm32fx_rcc_clock",
+ .soc = STM32F469,
};
struct stm32_rcc_clk stm32_rcc_clk_f7 = {
};
static const struct udevice_id stm32_rcc_ids[] = {
- {.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f4 },
+ {.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f42x },
+ {.compatible = "st,stm32f469-rcc", .data = (ulong)&stm32_rcc_clk_f469 },
{.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 },
{.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 },
{ }
PCIe controllers. The PCIe may works in RC or EP mode according to
RCW[HOST_AGT_PEX] setting.
+config PCIE_INTEL_FPGA
+ bool "Intel FPGA PCIe support"
+ depends on DM_PCI
+ help
+ Say Y here if you want to enable PCIe controller support on Intel
+ FPGA, example Stratix 10.
+
endif
obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o
obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
+obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel FPGA PCIe host controller driver
+ *
+ * Copyright (C) 2013-2018 Intel Corporation. All rights reserved
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+#include <asm/io.h>
+
+#define RP_TX_REG0 0x2000
+#define RP_TX_CNTRL 0x2004
+#define RP_TX_SOP BIT(0)
+#define RP_TX_EOP BIT(1)
+#define RP_RXCPL_STATUS 0x200C
+#define RP_RXCPL_SOP BIT(0)
+#define RP_RXCPL_EOP BIT(1)
+#define RP_RXCPL_REG 0x2008
+#define P2A_INT_STATUS 0x3060
+#define P2A_INT_STS_ALL 0xf
+#define P2A_INT_ENABLE 0x3070
+#define RP_CAP_OFFSET 0x70
+
+/* TLP configuration type 0 and 1 */
+#define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */
+#define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */
+#define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */
+#define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */
+#define TLP_PAYLOAD_SIZE 0x01
+#define TLP_READ_TAG 0x1d
+#define TLP_WRITE_TAG 0x10
+#define RP_DEVFN 0
+
+#define RP_CFG_ADDR(pcie, reg) \
+ ((pcie->hip_base) + (reg) + (1 << 20))
+#define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn))
+
+#define TLP_CFGRD_DW0(pcie, bus) \
+ ((((bus != pcie->first_busno) ? TLP_FMTTYPE_CFGRD0 \
+ : TLP_FMTTYPE_CFGRD1) << 24) | \
+ TLP_PAYLOAD_SIZE)
+
+#define TLP_CFGWR_DW0(pcie, bus) \
+ ((((bus != pcie->first_busno) ? TLP_FMTTYPE_CFGWR0 \
+ : TLP_FMTTYPE_CFGWR1) << 24) | \
+ TLP_PAYLOAD_SIZE)
+
+#define TLP_CFG_DW1(pcie, tag, be) \
+ (((TLP_REQ_ID(pcie->first_busno, RP_DEVFN)) << 16) | (tag << 8) | (be))
+#define TLP_CFG_DW2(bus, dev, fn, offset) \
+ (((bus) << 24) | ((dev) << 19) | ((fn) << 16) | (offset))
+
+#define TLP_COMP_STATUS(s) (((s) >> 13) & 7)
+#define TLP_BYTE_COUNT(s) (((s) >> 0) & 0xfff)
+#define TLP_HDR_SIZE 3
+#define TLP_LOOP 500
+#define DWORD_MASK 3
+
+#define IS_ROOT_PORT(pcie, bdf) \
+ ((PCI_BUS(bdf) == pcie->first_busno) ? true : false)
+
+#define PCI_EXP_LNKSTA 18 /* Link Status */
+#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
+
+/**
+ * struct intel_fpga_pcie - Intel FPGA PCIe controller state
+ * @bus: Pointer to the PCI bus
+ * @cra_base: The base address of CRA register space
+ * @hip_base: The base address of Rootport configuration space
+ * @first_busno: This driver supports multiple PCIe controllers.
+ * first_busno stores the bus number of the PCIe root-port
+ * number which may vary depending on the PCIe setup.
+ */
+struct intel_fpga_pcie {
+ struct udevice *bus;
+ void __iomem *cra_base;
+ void __iomem *hip_base;
+ int first_busno;
+};
+
+/**
+ * Intel FPGA PCIe port uses BAR0 of RC's configuration space as the
+ * translation from PCI bus to native BUS. Entire DDR region is mapped
+ * into PCIe space using these registers, so it can be reached by DMA from
+ * EP devices.
+ * The BAR0 of bridge should be hidden during enumeration to avoid the
+ * sizing and resource allocation by PCIe core.
+ */
+static bool intel_fpga_pcie_hide_rc_bar(struct intel_fpga_pcie *pcie,
+ pci_dev_t bdf, int offset)
+{
+ if (IS_ROOT_PORT(pcie, bdf) && PCI_DEV(bdf) == 0 &&
+ PCI_FUNC(bdf) == 0 && offset == PCI_BASE_ADDRESS_0)
+ return true;
+
+ return false;
+}
+
+static inline void cra_writel(struct intel_fpga_pcie *pcie, const u32 value,
+ const u32 reg)
+{
+ writel(value, pcie->cra_base + reg);
+}
+
+static inline u32 cra_readl(struct intel_fpga_pcie *pcie, const u32 reg)
+{
+ return readl(pcie->cra_base + reg);
+}
+
+static bool intel_fpga_pcie_link_up(struct intel_fpga_pcie *pcie)
+{
+ return !!(readw(RP_CFG_ADDR(pcie, RP_CAP_OFFSET + PCI_EXP_LNKSTA))
+ & PCI_EXP_LNKSTA_DLLLA);
+}
+
+static bool intel_fpga_pcie_addr_valid(struct intel_fpga_pcie *pcie,
+ pci_dev_t bdf)
+{
+ /* If there is no link, then there is no device */
+ if (!IS_ROOT_PORT(pcie, bdf) && !intel_fpga_pcie_link_up(pcie))
+ return false;
+
+ /* access only one slot on each root port */
+ if (IS_ROOT_PORT(pcie, bdf) && PCI_DEV(bdf) > 0)
+ return false;
+
+ if ((PCI_BUS(bdf) == pcie->first_busno + 1) && PCI_DEV(bdf) > 0)
+ return false;
+
+ return true;
+}
+
+static void tlp_write_tx(struct intel_fpga_pcie *pcie, u32 reg0, u32 ctrl)
+{
+ cra_writel(pcie, reg0, RP_TX_REG0);
+ cra_writel(pcie, ctrl, RP_TX_CNTRL);
+}
+
+static int tlp_read_packet(struct intel_fpga_pcie *pcie, u32 *value)
+{
+ int i;
+ u32 ctrl;
+ u32 comp_status;
+ u32 dw[4];
+ u32 count = 0;
+
+ for (i = 0; i < TLP_LOOP; i++) {
+ ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
+ if (!(ctrl & RP_RXCPL_SOP))
+ continue;
+
+ /* read first DW */
+ dw[count++] = cra_readl(pcie, RP_RXCPL_REG);
+
+ /* Poll for EOP */
+ for (i = 0; i < TLP_LOOP; i++) {
+ ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
+ dw[count++] = cra_readl(pcie, RP_RXCPL_REG);
+ if (ctrl & RP_RXCPL_EOP) {
+ comp_status = TLP_COMP_STATUS(dw[1]);
+ if (comp_status)
+ return -EFAULT;
+
+ if (value &&
+ TLP_BYTE_COUNT(dw[1]) == sizeof(u32) &&
+ count >= 3)
+ *value = dw[3];
+
+ return 0;
+ }
+ }
+
+ udelay(5);
+ }
+
+ dev_err(pcie->dev, "read TLP packet timed out\n");
+ return -ENODEV;
+}
+
+static void tlp_write_packet(struct intel_fpga_pcie *pcie, u32 *headers,
+ u32 data)
+{
+ tlp_write_tx(pcie, headers[0], RP_TX_SOP);
+
+ tlp_write_tx(pcie, headers[1], 0);
+
+ tlp_write_tx(pcie, headers[2], 0);
+
+ tlp_write_tx(pcie, data, RP_TX_EOP);
+}
+
+static int tlp_cfg_dword_read(struct intel_fpga_pcie *pcie, pci_dev_t bdf,
+ int offset, u8 byte_en, u32 *value)
+{
+ u32 headers[TLP_HDR_SIZE];
+ u8 busno = PCI_BUS(bdf);
+
+ headers[0] = TLP_CFGRD_DW0(pcie, busno);
+ headers[1] = TLP_CFG_DW1(pcie, TLP_READ_TAG, byte_en);
+ headers[2] = TLP_CFG_DW2(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset);
+
+ tlp_write_packet(pcie, headers, 0);
+
+ return tlp_read_packet(pcie, value);
+}
+
+static int tlp_cfg_dword_write(struct intel_fpga_pcie *pcie, pci_dev_t bdf,
+ int offset, u8 byte_en, u32 value)
+{
+ u32 headers[TLP_HDR_SIZE];
+ u8 busno = PCI_BUS(bdf);
+
+ headers[0] = TLP_CFGWR_DW0(pcie, busno);
+ headers[1] = TLP_CFG_DW1(pcie, TLP_WRITE_TAG, byte_en);
+ headers[2] = TLP_CFG_DW2(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset);
+
+ tlp_write_packet(pcie, headers, value);
+
+ return tlp_read_packet(pcie, NULL);
+}
+
+int intel_fpga_rp_conf_addr(struct udevice *bus, pci_dev_t bdf,
+ uint offset, void **paddress)
+{
+ struct intel_fpga_pcie *pcie = dev_get_priv(bus);
+
+ *paddress = RP_CFG_ADDR(pcie, offset);
+
+ return 0;
+}
+
+static int intel_fpga_pcie_rp_rd_conf(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong *valuep,
+ enum pci_size_t size)
+{
+ return pci_generic_mmap_read_config(bus, intel_fpga_rp_conf_addr,
+ bdf, offset, valuep, size);
+}
+
+static int intel_fpga_pcie_rp_wr_conf(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong value,
+ enum pci_size_t size)
+{
+ int ret;
+ struct intel_fpga_pcie *pcie = dev_get_priv(bus);
+
+ ret = pci_generic_mmap_write_config(bus, intel_fpga_rp_conf_addr,
+ bdf, offset, value, size);
+ if (!ret) {
+ /* Monitor changes to PCI_PRIMARY_BUS register on root port
+ * and update local copy of root bus number accordingly.
+ */
+ if (offset == PCI_PRIMARY_BUS)
+ pcie->first_busno = (u8)(value);
+ }
+
+ return ret;
+}
+
+static u8 pcie_get_byte_en(uint offset, enum pci_size_t size)
+{
+ switch (size) {
+ case PCI_SIZE_8:
+ return 1 << (offset & 3);
+ case PCI_SIZE_16:
+ return 3 << (offset & 3);
+ default:
+ return 0xf;
+ }
+}
+
+static int _pcie_intel_fpga_read_config(struct intel_fpga_pcie *pcie,
+ pci_dev_t bdf, uint offset,
+ ulong *valuep, enum pci_size_t size)
+{
+ int ret;
+ u32 data;
+ u8 byte_en;
+
+ /* Uses memory mapped method to read rootport config registers */
+ if (IS_ROOT_PORT(pcie, bdf))
+ return intel_fpga_pcie_rp_rd_conf(pcie->bus, bdf,
+ offset, valuep, size);
+
+ byte_en = pcie_get_byte_en(offset, size);
+ ret = tlp_cfg_dword_read(pcie, bdf, offset & ~DWORD_MASK,
+ byte_en, &data);
+ if (ret)
+ return ret;
+
+ dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08x)\n",
+ offset, size, data);
+ *valuep = pci_conv_32_to_size(data, offset, size);
+
+ return 0;
+}
+
+static int _pcie_intel_fpga_write_config(struct intel_fpga_pcie *pcie,
+ pci_dev_t bdf, uint offset,
+ ulong value, enum pci_size_t size)
+{
+ u32 data;
+ u8 byte_en;
+
+ dev_dbg(pcie->dev, "PCIE CFG write: (b.d.f)=(%02d.%02d.%02d)\n",
+ PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+ dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08lx)\n",
+ offset, size, value);
+
+ /* Uses memory mapped method to read rootport config registers */
+ if (IS_ROOT_PORT(pcie, bdf))
+ return intel_fpga_pcie_rp_wr_conf(pcie->bus, bdf, offset,
+ value, size);
+
+ byte_en = pcie_get_byte_en(offset, size);
+ data = pci_conv_size_to_32(0, value, offset, size);
+
+ return tlp_cfg_dword_write(pcie, bdf, offset & ~DWORD_MASK,
+ byte_en, data);
+}
+
+static int pcie_intel_fpga_read_config(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong *valuep,
+ enum pci_size_t size)
+{
+ struct intel_fpga_pcie *pcie = dev_get_priv(bus);
+
+ dev_dbg(pcie->dev, "PCIE CFG read: (b.d.f)=(%02d.%02d.%02d)\n",
+ PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+
+ if (intel_fpga_pcie_hide_rc_bar(pcie, bdf, offset)) {
+ *valuep = (u32)pci_get_ff(size);
+ return 0;
+ }
+
+ if (!intel_fpga_pcie_addr_valid(pcie, bdf)) {
+ *valuep = (u32)pci_get_ff(size);
+ return 0;
+ }
+
+ return _pcie_intel_fpga_read_config(pcie, bdf, offset, valuep, size);
+}
+
+static int pcie_intel_fpga_write_config(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong value,
+ enum pci_size_t size)
+{
+ struct intel_fpga_pcie *pcie = dev_get_priv(bus);
+
+ if (intel_fpga_pcie_hide_rc_bar(pcie, bdf, offset))
+ return 0;
+
+ if (!intel_fpga_pcie_addr_valid(pcie, bdf))
+ return 0;
+
+ return _pcie_intel_fpga_write_config(pcie, bdf, offset, value,
+ size);
+}
+
+static int pcie_intel_fpga_probe(struct udevice *dev)
+{
+ struct intel_fpga_pcie *pcie = dev_get_priv(dev);
+
+ pcie->bus = pci_get_controller(dev);
+ pcie->first_busno = dev->seq;
+
+ /* clear all interrupts */
+ cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS);
+ /* disable all interrupts */
+ cra_writel(pcie, 0, P2A_INT_ENABLE);
+
+ return 0;
+}
+
+static int pcie_intel_fpga_ofdata_to_platdata(struct udevice *dev)
+{
+ struct intel_fpga_pcie *pcie = dev_get_priv(dev);
+ struct fdt_resource reg_res;
+ int node = dev_of_offset(dev);
+ int ret;
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ ret = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names",
+ "Cra", ®_res);
+ if (ret) {
+ dev_err(dev, "resource \"Cra\" not found\n");
+ return ret;
+ }
+
+ pcie->cra_base = map_physmem(reg_res.start,
+ fdt_resource_size(®_res),
+ MAP_NOCACHE);
+
+ ret = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names",
+ "Hip", ®_res);
+ if (ret) {
+ dev_err(dev, "resource \"Hip\" not found\n");
+ return ret;
+ }
+
+ pcie->hip_base = map_physmem(reg_res.start,
+ fdt_resource_size(®_res),
+ MAP_NOCACHE);
+
+ return 0;
+}
+
+static const struct dm_pci_ops pcie_intel_fpga_ops = {
+ .read_config = pcie_intel_fpga_read_config,
+ .write_config = pcie_intel_fpga_write_config,
+};
+
+static const struct udevice_id pcie_intel_fpga_ids[] = {
+ { .compatible = "altr,pcie-root-port-2.0" },
+ {},
+};
+
+U_BOOT_DRIVER(pcie_intel_fpga) = {
+ .name = "pcie_intel_fpga",
+ .id = UCLASS_PCI,
+ .of_match = pcie_intel_fpga_ids,
+ .ops = &pcie_intel_fpga_ops,
+ .ofdata_to_platdata = pcie_intel_fpga_ofdata_to_platdata,
+ .probe = pcie_intel_fpga_probe,
+ .priv_auto_alloc_size = sizeof(struct intel_fpga_pcie),
+};
#include "pinctrl-meson.h"
-#define EE_OFF 14
+#define EE_OFF 15
static const unsigned int emmc_nand_d07_pins[] = {
PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF),
"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
"GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19",
"GPIOX_20", "GPIOX_21", "GPIOX_22",
-
- "GPIO_TEST_N",
};
static const char * const emmc_groups[] = {
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
"GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13",
+
+ "GPIO_TEST_N",
};
static const char * const uart_ao_groups[] = {
struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
.name = "periphs-banks",
- .pin_base = 14,
+ .pin_base = 15,
.groups = meson_gxbb_periphs_groups,
.funcs = meson_gxbb_periphs_functions,
.banks = meson_gxbb_periphs_banks,
- .num_pins = 120,
+ .num_pins = 119,
.num_groups = ARRAY_SIZE(meson_gxbb_periphs_groups),
.num_funcs = ARRAY_SIZE(meson_gxbb_periphs_functions),
.num_banks = ARRAY_SIZE(meson_gxbb_periphs_banks),
.groups = meson_gxbb_aobus_groups,
.funcs = meson_gxbb_aobus_functions,
.banks = meson_gxbb_aobus_banks,
- .num_pins = 14,
+ .num_pins = 15,
.num_groups = ARRAY_SIZE(meson_gxbb_aobus_groups),
.num_funcs = ARRAY_SIZE(meson_gxbb_aobus_functions),
.num_banks = ARRAY_SIZE(meson_gxbb_aobus_banks),
#include "pinctrl-meson.h"
-#define EE_OFF 10
+#define EE_OFF 11
static const unsigned int emmc_nand_d07_pins[] = {
PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF),
GPIO_GROUP(GPIOCLK_0, EE_OFF),
GPIO_GROUP(GPIOCLK_1, EE_OFF),
- GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+ GPIO_GROUP(GPIO_TEST_N, 0),
/* Bank X */
GROUP(sdio_d0, 5, 31),
"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
"GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18",
-
- "GPIO_TEST_N",
};
static const char * const emmc_groups[] = {
static const char * const gpio_aobus_groups[] = {
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
+
+ "GPIO_TEST_N",
};
static const char * const uart_ao_groups[] = {
struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data = {
.name = "periphs-banks",
- .pin_base = 10,
+ .pin_base = 11,
.groups = meson_gxl_periphs_groups,
.funcs = meson_gxl_periphs_functions,
.banks = meson_gxl_periphs_banks,
- .num_pins = 101,
+ .num_pins = 100,
.num_groups = ARRAY_SIZE(meson_gxl_periphs_groups),
.num_funcs = ARRAY_SIZE(meson_gxl_periphs_functions),
.num_banks = ARRAY_SIZE(meson_gxl_periphs_banks),
.groups = meson_gxl_aobus_groups,
.funcs = meson_gxl_aobus_functions,
.banks = meson_gxl_aobus_banks,
- .num_pins = 10,
+ .num_pins = 11,
.num_groups = ARRAY_SIZE(meson_gxl_aobus_groups),
.num_funcs = ARRAY_SIZE(meson_gxl_aobus_functions),
.num_banks = ARRAY_SIZE(meson_gxl_aobus_banks),
#define UNIPHIER_PINCTRL_PINMUX_BASE 0x1000
#define UNIPHIER_PINCTRL_LOAD_PINMUX 0x1700
+#define UNIPHIER_PINCTRL_DRVCTRL_BASE 0x1800
+#define UNIPHIER_PINCTRL_DRV2CTRL_BASE 0x1900
+#define UNIPHIER_PINCTRL_DRV3CTRL_BASE 0x1980
#define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00
#define UNIPHIER_PINCTRL_IECTRL 0x1d00
static const char *uniphier_pinctrl_dummy_name = "_dummy";
+static int uniphier_pinctrl_get_pins_count(struct udevice *dev)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
+ int pins_count = priv->socdata->pins_count;
+
+ /*
+ * We do not list all pins in the pin table to save memory footprint.
+ * Report the max pin number + 1 to fake the framework.
+ */
+ return pins[pins_count - 1].number + 1;
+}
+
+static const char *uniphier_pinctrl_get_pin_name(struct udevice *dev,
+ unsigned int selector)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
+ int pins_count = priv->socdata->pins_count;
+ int i;
+
+ for (i = 0; i < pins_count; i++)
+ if (pins[i].number == selector)
+ return pins[i].name;
+
+ return uniphier_pinctrl_dummy_name;
+}
+
static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
{
struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
};
+static const struct uniphier_pinctrl_pin *
+uniphier_pinctrl_pin_get(struct uniphier_pinctrl_priv *priv, unsigned int pin)
+{
+ const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
+ int pins_count = priv->socdata->pins_count;
+ int i;
+
+ for (i = 0; i < pins_count; i++)
+ if (pins[i].number == pin)
+ return &pins[i];
+
+ return NULL;
+}
+
static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
unsigned int param, unsigned int arg)
{
return 0;
}
-static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin,
- unsigned int param, unsigned int arg)
+static const unsigned int uniphier_pinconf_drv_strengths_1bit[] = {
+ 4, 8,
+};
+
+static const unsigned int uniphier_pinconf_drv_strengths_2bit[] = {
+ 8, 12, 16, 20,
+};
+
+static const unsigned int uniphier_pinconf_drv_strengths_3bit[] = {
+ 4, 5, 7, 9, 11, 12, 14, 16,
+};
+
+static int uniphier_pinconf_drive_set(struct udevice *dev, unsigned int pin,
+ unsigned int strength)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct uniphier_pinctrl_pin *desc;
+ const unsigned int *strengths;
+ unsigned int base, stride, width, drvctrl, reg, shift;
+ u32 val, mask, tmp;
+
+ desc = uniphier_pinctrl_pin_get(priv, pin);
+ if (WARN_ON(!desc))
+ return -EINVAL;
+
+ switch (uniphier_pin_get_drv_type(desc->data)) {
+ case UNIPHIER_PIN_DRV_1BIT:
+ strengths = uniphier_pinconf_drv_strengths_1bit;
+ base = UNIPHIER_PINCTRL_DRVCTRL_BASE;
+ stride = 1;
+ width = 1;
+ break;
+ case UNIPHIER_PIN_DRV_2BIT:
+ strengths = uniphier_pinconf_drv_strengths_2bit;
+ base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
+ stride = 2;
+ width = 2;
+ break;
+ case UNIPHIER_PIN_DRV_3BIT:
+ strengths = uniphier_pinconf_drv_strengths_3bit;
+ base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
+ stride = 4;
+ width = 3;
+ break;
+ default:
+ /* drive strength control is not supported for this pin */
+ return -EINVAL;
+ }
+
+ drvctrl = uniphier_pin_get_drvctrl(desc->data);
+ drvctrl *= stride;
+
+ reg = base + drvctrl / 32 * 4;
+ shift = drvctrl % 32;
+ mask = (1U << width) - 1;
+
+ for (val = 0; val <= mask; val++) {
+ if (strengths[val] > strength)
+ break;
+ }
+
+ if (val == 0) {
+ dev_err(dev, "unsupported drive strength %u mA for pin %s\n",
+ strength, desc->name);
+ return -EINVAL;
+ }
+
+ if (!mask)
+ return 0;
+
+ val--;
+
+ tmp = readl(priv->base + reg);
+ tmp &= ~(mask << shift);
+ tmp |= (mask & val) << shift;
+ writel(tmp, priv->base + reg);
+
+ return 0;
+}
+
+static int uniphier_pinconf_set(struct udevice *dev, unsigned int pin,
+ unsigned int param, unsigned int arg)
{
int ret;
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ret = uniphier_pinconf_drive_set(dev, pin, arg);
+ break;
case PIN_CONFIG_INPUT_ENABLE:
ret = uniphier_pinconf_input_enable(dev, pin, arg);
break;
default:
- printf("unsupported configuration parameter %u\n", param);
+ dev_err(dev, "unsupported configuration parameter %u\n", param);
return -EINVAL;
}
int i, ret;
for (i = 0; i < grp->num_pins; i++) {
- ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg);
+ ret = uniphier_pinconf_set(dev, grp->pins[i], param, arg);
if (ret)
return ret;
}
}
const struct pinctrl_ops uniphier_pinctrl_ops = {
+ .get_pins_count = uniphier_pinctrl_get_pins_count,
+ .get_pin_name = uniphier_pinctrl_get_pin_name,
.get_groups_count = uniphier_pinctrl_get_groups_count,
.get_group_name = uniphier_pinctrl_get_group_name,
.get_functions_count = uniphier_pinmux_get_functions_count,
#if CONFIG_IS_ENABLED(PINCONF)
.pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
.pinconf_params = uniphier_pinconf_params,
+ .pinconf_set = uniphier_pinconf_set,
.pinconf_group_set = uniphier_pinconf_group_set,
#endif
.set_state = pinctrl_generic_set_state,
#include "pinctrl-uniphier.h"
+static const struct uniphier_pinctrl_pin uniphier_ld20_pins[] = {
+ UNIPHIER_PINCTRL_PIN(40, "RGMII_TXCLK", 28, UNIPHIER_PIN_DRV_3BIT),
+ UNIPHIER_PINCTRL_PIN(41, "RGMII_TXD0", 29, UNIPHIER_PIN_DRV_3BIT),
+ UNIPHIER_PINCTRL_PIN(42, "RGMII_TXD1", 30, UNIPHIER_PIN_DRV_3BIT),
+ UNIPHIER_PINCTRL_PIN(43, "RGMII_TXD2", 31, UNIPHIER_PIN_DRV_3BIT),
+ UNIPHIER_PINCTRL_PIN(44, "RGMII_TXD3", 32, UNIPHIER_PIN_DRV_3BIT),
+ UNIPHIER_PINCTRL_PIN(45, "RGMII_TXCTL", 33, UNIPHIER_PIN_DRV_3BIT),
+};
+
static const unsigned emmc_pins[] = {18, 19, 20, 21, 22, 23, 24, 25};
static const int emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0};
static const unsigned emmc_dat8_pins[] = {26, 27, 28, 29};
};
static struct uniphier_pinctrl_socdata uniphier_ld20_pinctrl_socdata = {
+ .pins = uniphier_ld20_pins,
+ .pins_count = ARRAY_SIZE(uniphier_ld20_pins),
.groups = uniphier_ld20_groups,
.groups_count = ARRAY_SIZE(uniphier_ld20_groups),
.functions = uniphier_ld20_functions,
#include "pinctrl-uniphier.h"
-static const struct uniphier_pinctrl_pin uniphier_ld6b_pins[] = {
- UNIPHIER_PINCTRL_PIN(113, 0),
- UNIPHIER_PINCTRL_PIN(114, 0),
- UNIPHIER_PINCTRL_PIN(115, 0),
- UNIPHIER_PINCTRL_PIN(116, 0),
- UNIPHIER_PINCTRL_PIN(217, 0),
- UNIPHIER_PINCTRL_PIN(218, 0),
- UNIPHIER_PINCTRL_PIN(219, 0),
- UNIPHIER_PINCTRL_PIN(220, 0),
-};
-
static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
static const int emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
};
static struct uniphier_pinctrl_socdata uniphier_ld6b_pinctrl_socdata = {
- .pins = uniphier_ld6b_pins,
- .pins_count = ARRAY_SIZE(uniphier_ld6b_pins),
.groups = uniphier_ld6b_groups,
.groups_count = ARRAY_SIZE(uniphier_ld6b_groups),
.functions = uniphier_ld6b_functions,
#define __PINCTRL_UNIPHIER_H__
#include <linux/bitops.h>
-#include <linux/bug.h>
+#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#define UNIPHIER_PIN_ATTR_PACKED(iectrl) (iectrl)
+/* drive strength control register number */
+#define UNIPHIER_PIN_DRVCTRL_SHIFT 0
+#define UNIPHIER_PIN_DRVCTRL_BITS 9
+#define UNIPHIER_PIN_DRVCTRL_MASK ((1U << (UNIPHIER_PIN_DRVCTRL_BITS)) \
+ - 1)
+
+/* drive control type */
+#define UNIPHIER_PIN_DRV_TYPE_SHIFT ((UNIPHIER_PIN_DRVCTRL_SHIFT) + \
+ (UNIPHIER_PIN_DRVCTRL_BITS))
+#define UNIPHIER_PIN_DRV_TYPE_BITS 2
+#define UNIPHIER_PIN_DRV_TYPE_MASK ((1U << (UNIPHIER_PIN_DRV_TYPE_BITS)) \
+ - 1)
+
+/* drive control type */
+enum uniphier_pin_drv_type {
+ UNIPHIER_PIN_DRV_1BIT, /* 2 level control: 4/8 mA */
+ UNIPHIER_PIN_DRV_2BIT, /* 4 level control: 8/12/16/20 mA */
+ UNIPHIER_PIN_DRV_3BIT, /* 8 level control: 4/5/7/9/11/12/14/16 mA */
+};
+
+#define UNIPHIER_PIN_DRVCTRL(x) \
+ (((x) & (UNIPHIER_PIN_DRVCTRL_MASK)) << (UNIPHIER_PIN_DRVCTRL_SHIFT))
+#define UNIPHIER_PIN_DRV_TYPE(x) \
+ (((x) & (UNIPHIER_PIN_DRV_TYPE_MASK)) << (UNIPHIER_PIN_DRV_TYPE_SHIFT))
-static inline unsigned int uniphier_pin_get_iectrl(unsigned long data)
+#define UNIPHIER_PIN_ATTR_PACKED(drvctrl, drv_type) \
+ UNIPHIER_PIN_DRVCTRL(drvctrl) | \
+ UNIPHIER_PIN_DRV_TYPE(drv_type)
+
+static inline unsigned int uniphier_pin_get_drvctrl(unsigned int data)
{
- return data;
+ return (data >> UNIPHIER_PIN_DRVCTRL_SHIFT) & UNIPHIER_PIN_DRVCTRL_MASK;
+}
+
+static inline unsigned int uniphier_pin_get_drv_type(unsigned int data)
+{
+ return (data >> UNIPHIER_PIN_DRV_TYPE_SHIFT) &
+ UNIPHIER_PIN_DRV_TYPE_MASK;
}
/**
*/
struct uniphier_pinctrl_pin {
unsigned number;
- unsigned long data;
+ const char *name;
+ unsigned int data;
};
/**
#define UNIPHIER_PINCTRL_CAPS_MUX_4BIT BIT(0)
};
-#define UNIPHIER_PINCTRL_PIN(a, b) \
+#define UNIPHIER_PINCTRL_PIN(a, b, c, d) \
{ \
.number = a, \
- .data = UNIPHIER_PIN_ATTR_PACKED(b), \
+ .name = b, \
+ .data = UNIPHIER_PIN_ATTR_PACKED(c, d), \
}
#define __UNIPHIER_PINCTRL_GROUP(grp) \
#define STMPU1_NUM_OF_REGS 0x100
+#ifndef CONFIG_SPL_BUILD
+static const struct pmic_child_info stpmu1_children_info[] = {
+ { .prefix = "ldo", .driver = "stpmu1_ldo" },
+ { .prefix = "buck", .driver = "stpmu1_buck" },
+ { .prefix = "vref_ddr", .driver = "stpmu1_vref_ddr" },
+ { .prefix = "pwr_sw", .driver = "stpmu1_pwr_sw" },
+ { .prefix = "boost", .driver = "stpmu1_boost" },
+ { },
+};
+#endif /* CONFIG_SPL_BUILD */
+
static int stpmu1_reg_count(struct udevice *dev)
{
return STMPU1_NUM_OF_REGS;
return ret;
}
+static int stpmu1_bind(struct udevice *dev)
+{
+#ifndef CONFIG_SPL_BUILD
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ dev_dbg(dev, "regulators subnode not found!");
+ return -ENXIO;
+ }
+ dev_dbg(dev, "found regulators subnode\n");
+
+ children = pmic_bind_children(dev, regulators_node,
+ stpmu1_children_info);
+ if (!children)
+ dev_dbg(dev, "no child found\n");
+#endif /* CONFIG_SPL_BUILD */
+
+ return 0;
+}
+
static struct dm_pmic_ops stpmu1_ops = {
.reg_count = stpmu1_reg_count,
.read = stpmu1_read,
.name = "stpmu1_pmic",
.id = UCLASS_PMIC,
.of_match = stpmu1_ids,
+ .bind = stpmu1_bind,
.ops = &stpmu1_ops,
};
be configured in multi phase modes. The driver implements
get/set api for value and enable.
+config DM_REGULATOR_STM32_VREFBUF
+ bool "Enable driver for STMicroelectronics STM32 VREFBUF"
+ depends on DM_REGULATOR && (STM32H7 || ARCH_STM32MP)
+ help
+ This driver supports STMicroelectronics STM32 VREFBUF (voltage
+ reference buffer) which can be used as voltage reference for
+ internal ADCs, DACs and also for external components through
+ dedicated Vref+ pin.
+
config DM_REGULATOR_TPS65910
bool "Enable driver for TPS65910 PMIC regulators"
depends on DM_PMIC_TPS65910
The TPS65910 PMIC provides 4 SMPSs and 8 LDOs. This driver supports all
regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements
the get/set api for value and enable.
+
+config DM_REGULATOR_STPMU1
+ bool "Enable driver for STPMU1 regulators"
+ depends on DM_REGULATOR && PMIC_STPMU1
+ ---help---
+ Enable support for the regulator functions of the STPMU1 PMIC. The
+ driver implements get/set api for the various BUCKS and LDOs supported
+ by the PMIC device. This driver is controlled by a device tree node
+ which includes voltage limits.
obj-$(CONFIG_$(SPL_)DM_REGULATOR_PBIAS) += pbias_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMU1) += stpmu1.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.16 drivers/regulator/stm32-vrefbuf.c
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <power/regulator.h>
+
+/* STM32 VREFBUF registers */
+#define STM32_VREFBUF_CSR 0x00
+
+/* STM32 VREFBUF CSR bitfields */
+#define STM32_VRS GENMASK(6, 4)
+#define STM32_VRS_SHIFT 4
+#define STM32_VRR BIT(3)
+#define STM32_HIZ BIT(1)
+#define STM32_ENVR BIT(0)
+
+struct stm32_vrefbuf {
+ void __iomem *base;
+ struct clk clk;
+ struct udevice *vdda_supply;
+};
+
+static const unsigned int stm32_vrefbuf_voltages[] = {
+ /* Matches resp. VRS = 000b, 001b, 010b, 011b */
+ 2500000, 2048000, 1800000, 1500000,
+};
+
+static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable)
+{
+ struct stm32_vrefbuf *priv = dev_get_priv(dev);
+ u32 val;
+ int ret;
+
+ clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ | STM32_ENVR,
+ enable ? STM32_ENVR : STM32_HIZ);
+ if (!enable)
+ return 0;
+
+ /*
+ * Vrefbuf startup time depends on external capacitor: wait here for
+ * VRR to be set. That means output has reached expected value.
+ * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
+ * arbitrary timeout.
+ */
+ ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
+ val & STM32_VRR, 10000);
+ if (ret < 0) {
+ dev_err(dev, "stm32 vrefbuf timed out: %d\n", ret);
+ clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
+ STM32_HIZ);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stm32_vrefbuf_get_enable(struct udevice *dev)
+{
+ struct stm32_vrefbuf *priv = dev_get_priv(dev);
+
+ return readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
+}
+
+static int stm32_vrefbuf_set_value(struct udevice *dev, int uV)
+{
+ struct stm32_vrefbuf *priv = dev_get_priv(dev);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(stm32_vrefbuf_voltages); i++) {
+ if (uV == stm32_vrefbuf_voltages[i]) {
+ clrsetbits_le32(priv->base + STM32_VREFBUF_CSR,
+ STM32_VRS, i << STM32_VRS_SHIFT);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int stm32_vrefbuf_get_value(struct udevice *dev)
+{
+ struct stm32_vrefbuf *priv = dev_get_priv(dev);
+ u32 val;
+
+ val = readl(priv->base + STM32_VREFBUF_CSR) & STM32_VRS;
+ val >>= STM32_VRS_SHIFT;
+
+ return stm32_vrefbuf_voltages[val];
+}
+
+static const struct dm_regulator_ops stm32_vrefbuf_ops = {
+ .get_value = stm32_vrefbuf_get_value,
+ .set_value = stm32_vrefbuf_set_value,
+ .get_enable = stm32_vrefbuf_get_enable,
+ .set_enable = stm32_vrefbuf_set_enable,
+};
+
+static int stm32_vrefbuf_probe(struct udevice *dev)
+{
+ struct stm32_vrefbuf *priv = dev_get_priv(dev);
+ int ret;
+
+ priv->base = dev_read_addr_ptr(dev);
+
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret) {
+ dev_err(dev, "Can't get clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(&priv->clk);
+ if (ret) {
+ dev_err(dev, "Can't enable clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = device_get_supply_regulator(dev, "vdda-supply",
+ &priv->vdda_supply);
+ if (ret) {
+ dev_dbg(dev, "No vdda-supply: %d\n", ret);
+ return 0;
+ }
+
+ ret = regulator_set_enable(priv->vdda_supply, true);
+ if (ret) {
+ dev_err(dev, "Can't enable vdda-supply: %d\n", ret);
+ clk_disable(&priv->clk);
+ }
+
+ return ret;
+}
+
+static const struct udevice_id stm32_vrefbuf_ids[] = {
+ { .compatible = "st,stm32-vrefbuf" },
+ { }
+};
+
+U_BOOT_DRIVER(stm32_vrefbuf) = {
+ .name = "stm32-vrefbuf",
+ .id = UCLASS_REGULATOR,
+ .of_match = stm32_vrefbuf_ids,
+ .probe = stm32_vrefbuf_probe,
+ .ops = &stm32_vrefbuf_ops,
+ .priv_auto_alloc_size = sizeof(struct stm32_vrefbuf),
+};
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Christophe Kerello <christophe.kerello@st.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/stpmu1.h>
+
+struct stpmu1_range {
+ int min_uv;
+ int min_sel;
+ int max_sel;
+ int step;
+};
+
+struct stpmu1_output_range {
+ const struct stpmu1_range *ranges;
+ int nbranges;
+};
+
+#define STPMU1_MODE(_id, _val, _name) { \
+ .id = _id, \
+ .register_value = _val, \
+ .name = _name, \
+}
+
+#define STPMU1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \
+ .min_uv = _min_uv, \
+ .min_sel = _min_sel, \
+ .max_sel = _max_sel, \
+ .step = _step, \
+}
+
+#define STPMU1_OUTPUT_RANGE(_ranges, _nbranges) { \
+ .ranges = _ranges, \
+ .nbranges = _nbranges, \
+}
+
+static int stpmu1_output_find_uv(int sel,
+ const struct stpmu1_output_range *output_range)
+{
+ const struct stpmu1_range *range;
+ int i;
+
+ for (i = 0, range = output_range->ranges;
+ i < output_range->nbranges; i++, range++) {
+ if (sel >= range->min_sel && sel <= range->max_sel)
+ return range->min_uv +
+ (sel - range->min_sel) * range->step;
+ }
+
+ return -EINVAL;
+}
+
+static int stpmu1_output_find_sel(int uv,
+ const struct stpmu1_output_range *output_range)
+{
+ const struct stpmu1_range *range;
+ int i;
+
+ for (i = 0, range = output_range->ranges;
+ i < output_range->nbranges; i++, range++) {
+ if (uv == range->min_uv && !range->step)
+ return range->min_sel;
+
+ if (uv >= range->min_uv &&
+ uv <= range->min_uv +
+ (range->max_sel - range->min_sel) * range->step)
+ return range->min_sel +
+ (uv - range->min_uv) / range->step;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * BUCK regulators
+ */
+
+static const struct stpmu1_range buck1_ranges[] = {
+ STPMU1_RANGE(600000, 0, 30, 25000),
+ STPMU1_RANGE(1350000, 31, 63, 0),
+};
+
+static const struct stpmu1_range buck2_ranges[] = {
+ STPMU1_RANGE(1000000, 0, 17, 0),
+ STPMU1_RANGE(1050000, 18, 19, 0),
+ STPMU1_RANGE(1100000, 20, 21, 0),
+ STPMU1_RANGE(1150000, 22, 23, 0),
+ STPMU1_RANGE(1200000, 24, 25, 0),
+ STPMU1_RANGE(1250000, 26, 27, 0),
+ STPMU1_RANGE(1300000, 28, 29, 0),
+ STPMU1_RANGE(1350000, 30, 31, 0),
+ STPMU1_RANGE(1400000, 32, 33, 0),
+ STPMU1_RANGE(1450000, 34, 35, 0),
+ STPMU1_RANGE(1500000, 36, 63, 0),
+};
+
+static const struct stpmu1_range buck3_ranges[] = {
+ STPMU1_RANGE(1000000, 0, 19, 0),
+ STPMU1_RANGE(1100000, 20, 23, 0),
+ STPMU1_RANGE(1200000, 24, 27, 0),
+ STPMU1_RANGE(1300000, 28, 31, 0),
+ STPMU1_RANGE(1400000, 32, 35, 0),
+ STPMU1_RANGE(1500000, 36, 55, 100000),
+ STPMU1_RANGE(3400000, 56, 63, 0),
+};
+
+static const struct stpmu1_range buck4_ranges[] = {
+ STPMU1_RANGE(600000, 0, 27, 25000),
+ STPMU1_RANGE(1300000, 28, 29, 0),
+ STPMU1_RANGE(1350000, 30, 31, 0),
+ STPMU1_RANGE(1400000, 32, 33, 0),
+ STPMU1_RANGE(1450000, 34, 35, 0),
+ STPMU1_RANGE(1500000, 36, 60, 100000),
+ STPMU1_RANGE(3900000, 61, 63, 0),
+};
+
+/* BUCK: 1,2,3,4 - voltage ranges */
+static const struct stpmu1_output_range buck_voltage_range[] = {
+ STPMU1_OUTPUT_RANGE(buck1_ranges, ARRAY_SIZE(buck1_ranges)),
+ STPMU1_OUTPUT_RANGE(buck2_ranges, ARRAY_SIZE(buck2_ranges)),
+ STPMU1_OUTPUT_RANGE(buck3_ranges, ARRAY_SIZE(buck3_ranges)),
+ STPMU1_OUTPUT_RANGE(buck4_ranges, ARRAY_SIZE(buck4_ranges)),
+};
+
+/* BUCK modes */
+static const struct dm_regulator_mode buck_modes[] = {
+ STPMU1_MODE(STPMU1_BUCK_MODE_HP, STPMU1_BUCK_MODE_HP, "HP"),
+ STPMU1_MODE(STPMU1_BUCK_MODE_LP, STPMU1_BUCK_MODE_LP, "LP"),
+};
+
+static int stpmu1_buck_get_uv(struct udevice *dev, int buck)
+{
+ int sel;
+
+ sel = pmic_reg_read(dev, STPMU1_BUCKX_CTRL_REG(buck));
+ if (sel < 0)
+ return sel;
+
+ sel &= STPMU1_BUCK_OUTPUT_MASK;
+ sel >>= STPMU1_BUCK_OUTPUT_SHIFT;
+
+ return stpmu1_output_find_uv(sel, &buck_voltage_range[buck]);
+}
+
+static int stpmu1_buck_get_value(struct udevice *dev)
+{
+ return stpmu1_buck_get_uv(dev->parent, dev->driver_data - 1);
+}
+
+static int stpmu1_buck_set_value(struct udevice *dev, int uv)
+{
+ int sel, buck = dev->driver_data - 1;
+
+ sel = stpmu1_output_find_sel(uv, &buck_voltage_range[buck]);
+ if (sel < 0)
+ return sel;
+
+ return pmic_clrsetbits(dev->parent,
+ STPMU1_BUCKX_CTRL_REG(buck),
+ STPMU1_BUCK_OUTPUT_MASK,
+ sel << STPMU1_BUCK_OUTPUT_SHIFT);
+}
+
+static int stpmu1_buck_get_enable(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent,
+ STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1));
+ if (ret < 0)
+ return false;
+
+ return ret & STPMU1_BUCK_EN ? true : false;
+}
+
+static int stpmu1_buck_set_enable(struct udevice *dev, bool enable)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+ int ret, uv;
+
+ /* if regulator is already in the wanted state, nothing to do */
+ if (stpmu1_buck_get_enable(dev) == enable)
+ return 0;
+
+ if (enable) {
+ uc_pdata = dev_get_uclass_platdata(dev);
+ uv = stpmu1_buck_get_value(dev);
+ if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV))
+ stpmu1_buck_set_value(dev, uc_pdata->min_uV);
+ }
+
+ ret = pmic_clrsetbits(dev->parent,
+ STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1),
+ STPMU1_BUCK_EN, enable ? STPMU1_BUCK_EN : 0);
+ if (enable)
+ mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+ return ret;
+}
+
+static int stpmu1_buck_get_mode(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent,
+ STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1));
+ if (ret < 0)
+ return ret;
+
+ return ret & STPMU1_BUCK_MODE ? STPMU1_BUCK_MODE_LP :
+ STPMU1_BUCK_MODE_HP;
+}
+
+static int stpmu1_buck_set_mode(struct udevice *dev, int mode)
+{
+ return pmic_clrsetbits(dev->parent,
+ STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1),
+ STPMU1_BUCK_MODE,
+ mode ? STPMU1_BUCK_MODE : 0);
+}
+
+static int stpmu1_buck_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ if (!dev->driver_data || dev->driver_data > STPMU1_MAX_BUCK)
+ return -EINVAL;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_BUCK;
+ uc_pdata->mode = (struct dm_regulator_mode *)buck_modes;
+ uc_pdata->mode_count = ARRAY_SIZE(buck_modes);
+
+ return 0;
+}
+
+static const struct dm_regulator_ops stpmu1_buck_ops = {
+ .get_value = stpmu1_buck_get_value,
+ .set_value = stpmu1_buck_set_value,
+ .get_enable = stpmu1_buck_get_enable,
+ .set_enable = stpmu1_buck_set_enable,
+ .get_mode = stpmu1_buck_get_mode,
+ .set_mode = stpmu1_buck_set_mode,
+};
+
+U_BOOT_DRIVER(stpmu1_buck) = {
+ .name = "stpmu1_buck",
+ .id = UCLASS_REGULATOR,
+ .ops = &stpmu1_buck_ops,
+ .probe = stpmu1_buck_probe,
+};
+
+/*
+ * LDO regulators
+ */
+
+static const struct stpmu1_range ldo12_ranges[] = {
+ STPMU1_RANGE(1700000, 0, 7, 0),
+ STPMU1_RANGE(1700000, 8, 24, 100000),
+ STPMU1_RANGE(3300000, 25, 31, 0),
+};
+
+static const struct stpmu1_range ldo3_ranges[] = {
+ STPMU1_RANGE(1700000, 0, 7, 0),
+ STPMU1_RANGE(1700000, 8, 24, 100000),
+ STPMU1_RANGE(3300000, 25, 30, 0),
+ /* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */
+};
+
+static const struct stpmu1_range ldo5_ranges[] = {
+ STPMU1_RANGE(1700000, 0, 7, 0),
+ STPMU1_RANGE(1700000, 8, 30, 100000),
+ STPMU1_RANGE(3900000, 31, 31, 0),
+};
+
+static const struct stpmu1_range ldo6_ranges[] = {
+ STPMU1_RANGE(900000, 0, 24, 100000),
+ STPMU1_RANGE(3300000, 25, 31, 0),
+};
+
+/* LDO: 1,2,3,4,5,6 - voltage ranges */
+static const struct stpmu1_output_range ldo_voltage_range[] = {
+ STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
+ STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
+ STPMU1_OUTPUT_RANGE(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)),
+ STPMU1_OUTPUT_RANGE(NULL, 0),
+ STPMU1_OUTPUT_RANGE(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)),
+ STPMU1_OUTPUT_RANGE(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)),
+};
+
+/* LDO modes */
+static const struct dm_regulator_mode ldo_modes[] = {
+ STPMU1_MODE(STPMU1_LDO_MODE_NORMAL,
+ STPMU1_LDO_MODE_NORMAL, "NORMAL"),
+ STPMU1_MODE(STPMU1_LDO_MODE_BYPASS,
+ STPMU1_LDO_MODE_BYPASS, "BYPASS"),
+ STPMU1_MODE(STPMU1_LDO_MODE_SINK_SOURCE,
+ STPMU1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"),
+};
+
+static int stpmu1_ldo_get_value(struct udevice *dev)
+{
+ int sel, ldo = dev->driver_data - 1;
+
+ sel = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
+ if (sel < 0)
+ return sel;
+
+ /* ldo4 => 3,3V */
+ if (ldo == STPMU1_LDO4)
+ return STPMU1_LDO4_UV;
+
+ sel &= STPMU1_LDO12356_OUTPUT_MASK;
+ sel >>= STPMU1_LDO12356_OUTPUT_SHIFT;
+
+ /* ldo3, sel = 31 => BUCK2/2 */
+ if (ldo == STPMU1_LDO3 && sel == STPMU1_LDO3_DDR_SEL)
+ return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2;
+
+ return stpmu1_output_find_uv(sel, &ldo_voltage_range[ldo]);
+}
+
+static int stpmu1_ldo_set_value(struct udevice *dev, int uv)
+{
+ int sel, ldo = dev->driver_data - 1;
+
+ /* ldo4 => not possible */
+ if (ldo == STPMU1_LDO4)
+ return -EINVAL;
+
+ sel = stpmu1_output_find_sel(uv, &ldo_voltage_range[ldo]);
+ if (sel < 0)
+ return sel;
+
+ return pmic_clrsetbits(dev->parent,
+ STPMU1_LDOX_CTRL_REG(ldo),
+ STPMU1_LDO12356_OUTPUT_MASK,
+ sel << STPMU1_LDO12356_OUTPUT_SHIFT);
+}
+
+static int stpmu1_ldo_get_enable(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent,
+ STPMU1_LDOX_CTRL_REG(dev->driver_data - 1));
+ if (ret < 0)
+ return false;
+
+ return ret & STPMU1_LDO_EN ? true : false;
+}
+
+static int stpmu1_ldo_set_enable(struct udevice *dev, bool enable)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+ int ret, uv;
+
+ /* if regulator is already in the wanted state, nothing to do */
+ if (stpmu1_ldo_get_enable(dev) == enable)
+ return 0;
+
+ if (enable) {
+ uc_pdata = dev_get_uclass_platdata(dev);
+ uv = stpmu1_ldo_get_value(dev);
+ if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV))
+ stpmu1_ldo_set_value(dev, uc_pdata->min_uV);
+ }
+
+ ret = pmic_clrsetbits(dev->parent,
+ STPMU1_LDOX_CTRL_REG(dev->driver_data - 1),
+ STPMU1_LDO_EN, enable ? STPMU1_LDO_EN : 0);
+ if (enable)
+ mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+ return ret;
+}
+
+static int stpmu1_ldo_get_mode(struct udevice *dev)
+{
+ int ret, ldo = dev->driver_data - 1;
+
+ if (ldo != STPMU1_LDO3)
+ return -EINVAL;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
+ if (ret < 0)
+ return ret;
+
+ if (ret & STPMU1_LDO3_MODE)
+ return STPMU1_LDO_MODE_BYPASS;
+
+ ret &= STPMU1_LDO12356_OUTPUT_MASK;
+ ret >>= STPMU1_LDO12356_OUTPUT_SHIFT;
+
+ return ret == STPMU1_LDO3_DDR_SEL ? STPMU1_LDO_MODE_SINK_SOURCE :
+ STPMU1_LDO_MODE_NORMAL;
+}
+
+static int stpmu1_ldo_set_mode(struct udevice *dev, int mode)
+{
+ int ret, ldo = dev->driver_data - 1;
+
+ if (ldo != STPMU1_LDO3)
+ return -EINVAL;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
+ if (ret < 0)
+ return ret;
+
+ switch (mode) {
+ case STPMU1_LDO_MODE_SINK_SOURCE:
+ ret &= ~STPMU1_LDO12356_OUTPUT_MASK;
+ ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
+ case STPMU1_LDO_MODE_NORMAL:
+ ret &= ~STPMU1_LDO3_MODE;
+ break;
+ case STPMU1_LDO_MODE_BYPASS:
+ ret |= STPMU1_LDO3_MODE;
+ break;
+ }
+
+ return pmic_reg_write(dev->parent, STPMU1_LDOX_CTRL_REG(ldo), ret);
+}
+
+static int stpmu1_ldo_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ if (!dev->driver_data || dev->driver_data > STPMU1_MAX_LDO)
+ return -EINVAL;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_LDO;
+ if (dev->driver_data - 1 == STPMU1_LDO3) {
+ uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes;
+ uc_pdata->mode_count = ARRAY_SIZE(ldo_modes);
+ } else {
+ uc_pdata->mode_count = 0;
+ }
+
+ return 0;
+}
+
+static const struct dm_regulator_ops stpmu1_ldo_ops = {
+ .get_value = stpmu1_ldo_get_value,
+ .set_value = stpmu1_ldo_set_value,
+ .get_enable = stpmu1_ldo_get_enable,
+ .set_enable = stpmu1_ldo_set_enable,
+ .get_mode = stpmu1_ldo_get_mode,
+ .set_mode = stpmu1_ldo_set_mode,
+};
+
+U_BOOT_DRIVER(stpmu1_ldo) = {
+ .name = "stpmu1_ldo",
+ .id = UCLASS_REGULATOR,
+ .ops = &stpmu1_ldo_ops,
+ .probe = stpmu1_ldo_probe,
+};
+
+/*
+ * VREF DDR regulator
+ */
+
+static int stpmu1_vref_ddr_get_value(struct udevice *dev)
+{
+ /* BUCK2/2 */
+ return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2;
+}
+
+static int stpmu1_vref_ddr_get_enable(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_VREF_CTRL_REG);
+ if (ret < 0)
+ return false;
+
+ return ret & STPMU1_VREF_EN ? true : false;
+}
+
+static int stpmu1_vref_ddr_set_enable(struct udevice *dev, bool enable)
+{
+ int ret;
+
+ /* if regulator is already in the wanted state, nothing to do */
+ if (stpmu1_vref_ddr_get_enable(dev) == enable)
+ return 0;
+
+ ret = pmic_clrsetbits(dev->parent, STPMU1_VREF_CTRL_REG,
+ STPMU1_VREF_EN, enable ? STPMU1_VREF_EN : 0);
+ if (enable)
+ mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+ return ret;
+}
+
+static int stpmu1_vref_ddr_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_FIXED;
+ uc_pdata->mode_count = 0;
+
+ return 0;
+}
+
+static const struct dm_regulator_ops stpmu1_vref_ddr_ops = {
+ .get_value = stpmu1_vref_ddr_get_value,
+ .get_enable = stpmu1_vref_ddr_get_enable,
+ .set_enable = stpmu1_vref_ddr_set_enable,
+};
+
+U_BOOT_DRIVER(stpmu1_vref_ddr) = {
+ .name = "stpmu1_vref_ddr",
+ .id = UCLASS_REGULATOR,
+ .ops = &stpmu1_vref_ddr_ops,
+ .probe = stpmu1_vref_ddr_probe,
+};
+
+/*
+ * BOOST regulator
+ */
+
+static int stpmu1_boost_get_enable(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
+ if (ret < 0)
+ return false;
+
+ return ret & STPMU1_USB_BOOST_EN ? true : false;
+}
+
+static int stpmu1_boost_set_enable(struct udevice *dev, bool enable)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
+ if (ret < 0)
+ return ret;
+
+ if (!enable && ret & STPMU1_USB_PWR_SW_EN)
+ return -EINVAL;
+
+ /* if regulator is already in the wanted state, nothing to do */
+ if (!!(ret & STPMU1_USB_BOOST_EN) == enable)
+ return 0;
+
+ ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
+ STPMU1_USB_BOOST_EN,
+ enable ? STPMU1_USB_BOOST_EN : 0);
+ if (enable)
+ mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS);
+
+ return ret;
+}
+
+static int stpmu1_boost_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_FIXED;
+ uc_pdata->mode_count = 0;
+
+ return 0;
+}
+
+static const struct dm_regulator_ops stpmu1_boost_ops = {
+ .get_enable = stpmu1_boost_get_enable,
+ .set_enable = stpmu1_boost_set_enable,
+};
+
+U_BOOT_DRIVER(stpmu1_boost) = {
+ .name = "stpmu1_boost",
+ .id = UCLASS_REGULATOR,
+ .ops = &stpmu1_boost_ops,
+ .probe = stpmu1_boost_probe,
+};
+
+/*
+ * USB power switch
+ */
+
+static int stpmu1_pwr_sw_get_enable(struct udevice *dev)
+{
+ uint mask = 1 << dev->driver_data;
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
+ if (ret < 0)
+ return false;
+
+ return ret & mask ? true : false;
+}
+
+static int stpmu1_pwr_sw_set_enable(struct udevice *dev, bool enable)
+{
+ uint mask = 1 << dev->driver_data;
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
+ if (ret < 0)
+ return ret;
+
+ /* if regulator is already in the wanted state, nothing to do */
+ if (!!(ret & mask) == enable)
+ return 0;
+
+ /* Boost management */
+ if (enable && !(ret & STPMU1_USB_BOOST_EN)) {
+ pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
+ STPMU1_USB_BOOST_EN, STPMU1_USB_BOOST_EN);
+ mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS);
+ } else if (!enable && ret & STPMU1_USB_BOOST_EN &&
+ (ret & STPMU1_USB_PWR_SW_EN) != STPMU1_USB_PWR_SW_EN) {
+ pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
+ STPMU1_USB_BOOST_EN, 0);
+ }
+
+ ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
+ mask, enable ? mask : 0);
+ if (enable)
+ mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+
+ return ret;
+}
+
+static int stpmu1_pwr_sw_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ if (!dev->driver_data || dev->driver_data > STPMU1_MAX_PWR_SW)
+ return -EINVAL;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_FIXED;
+ uc_pdata->mode_count = 0;
+
+ return 0;
+}
+
+static const struct dm_regulator_ops stpmu1_pwr_sw_ops = {
+ .get_enable = stpmu1_pwr_sw_get_enable,
+ .set_enable = stpmu1_pwr_sw_set_enable,
+};
+
+U_BOOT_DRIVER(stpmu1_pwr_sw) = {
+ .name = "stpmu1_pwr_sw",
+ .id = UCLASS_REGULATOR,
+ .ops = &stpmu1_pwr_sw_ops,
+ .probe = stpmu1_pwr_sw_probe,
+};
#define MESON_FDTFILE_SETTING "fdtfile=amlogic/meson-gxl-s905x-khadas-vim.dtb\0"
-#include <configs/meson-gxbb-common.h>
+#include <configs/meson-gx-common.h>
#endif /* __CONFIG_H */
#define MESON_FDTFILE_SETTING "fdtfile=amlogic/meson-gxl-s905x-libretech-cc.dtb\0"
-#include <configs/meson-gxbb-common.h>
+#include <configs/meson-gx-common.h>
#endif /* __CONFIG_H */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration for Amlogic Meson GX SoCs
+ * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
+ */
+
+#ifndef __MESON_GX_COMMON_CONFIG_H
+#define __MESON_GX_COMMON_CONFIG_H
+
+#define CONFIG_CPU_ARMV8
+#define CONFIG_REMAKE_ELF
+#define CONFIG_NR_DRAM_BANKS 1
+#define CONFIG_ENV_SIZE 0x2000
+#define CONFIG_SYS_MAXARGS 32
+#define CONFIG_SYS_MALLOC_LEN (32 << 20)
+#define CONFIG_SYS_CBSIZE 1024
+
+#define CONFIG_SYS_SDRAM_BASE 0
+#define CONFIG_SYS_INIT_SP_ADDR 0x20000000
+#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_TEXT_BASE
+
+/* Generic Interrupt Controller Definitions */
+#define GICD_BASE 0xc4301000
+#define GICC_BASE 0xc4302000
+
+#define BOOT_TARGET_DEVICES(func) \
+ func(MMC, mmc, 0) \
+ func(MMC, mmc, 1) \
+ func(MMC, mmc, 2) \
+ func(PXE, pxe, na) \
+ func(DHCP, dhcp, na)
+
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "fdt_addr_r=0x01000000\0" \
+ "scriptaddr=0x1f000000\0" \
+ "kernel_addr_r=0x01080000\0" \
+ "pxefile_addr_r=0x01080000\0" \
+ "ramdisk_addr_r=0x13000000\0" \
+ MESON_FDTFILE_SETTING \
+ BOOTENV
+
+#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64 MiB */
+
+#endif /* __MESON_GX_COMMON_CONFIG_H */
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Configuration for Amlogic Meson GXBB SoCs
- * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
- */
-
-#ifndef __MESON_GXBB_COMMON_CONFIG_H
-#define __MESON_GXBB_COMMON_CONFIG_H
-
-#define CONFIG_CPU_ARMV8
-#define CONFIG_REMAKE_ELF
-#define CONFIG_NR_DRAM_BANKS 1
-#define CONFIG_ENV_SIZE 0x2000
-#define CONFIG_SYS_MAXARGS 32
-#define CONFIG_SYS_MALLOC_LEN (32 << 20)
-#define CONFIG_SYS_CBSIZE 1024
-
-#define CONFIG_SYS_SDRAM_BASE 0
-#define CONFIG_SYS_INIT_SP_ADDR 0x20000000
-#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_TEXT_BASE
-
-/* Generic Interrupt Controller Definitions */
-#define GICD_BASE 0xc4301000
-#define GICC_BASE 0xc4302000
-
-#define BOOT_TARGET_DEVICES(func) \
- func(MMC, mmc, 0) \
- func(MMC, mmc, 1) \
- func(MMC, mmc, 2) \
- func(PXE, pxe, na) \
- func(DHCP, dhcp, na)
-
-#include <config_distro_bootcmd.h>
-
-#define CONFIG_EXTRA_ENV_SETTINGS \
- "fdt_addr_r=0x01000000\0" \
- "scriptaddr=0x1f000000\0" \
- "kernel_addr_r=0x01080000\0" \
- "pxefile_addr_r=0x01080000\0" \
- "ramdisk_addr_r=0x13000000\0" \
- MESON_FDTFILE_SETTING \
- BOOTENV
-
-#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64 MiB */
-
-#endif /* __MESON_GXBB_COMMON_CONFIG_H */
#define MESON_FDTFILE_SETTING "fdtfile=amlogic/meson-gxbb-odroidc2.dtb\0"
-#include <configs/meson-gxbb-common.h>
+#include <configs/meson-gx-common.h>
#endif /* __CONFIG_H */
#define MESON_FDTFILE_SETTING "fdtfile=amlogic/meson-gxl-s905x-p212.dtb\0"
-#include <configs/meson-gxbb-common.h>
+#include <configs/meson-gx-common.h>
#endif /* __CONFIG_H */
#define CLKID_AO_UART1 3
#define CLKID_AO_UART2 4
#define CLKID_AO_IR_BLASTER 5
+#define CLKID_AO_CEC_32K 6
#endif
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* GXBB clock tree IDs
*/
#ifndef __GXBB_CLKC_H
#define __GXBB_CLKC_H
+#define CLKID_SYS_PLL 0
#define CLKID_HDMI_PLL 2
+#define CLKID_FIXED_PLL 3
#define CLKID_FCLK_DIV2 4
#define CLKID_FCLK_DIV3 5
#define CLKID_FCLK_DIV4 6
+#define CLKID_FCLK_DIV5 7
+#define CLKID_FCLK_DIV7 8
#define CLKID_GP0_PLL 9
#define CLKID_CLK81 12
+#define CLKID_MPLL0 13
+#define CLKID_MPLL1 14
#define CLKID_MPLL2 15
+#define CLKID_DDR 16
+#define CLKID_DOS 17
+#define CLKID_ISA 18
+#define CLKID_PL301 19
+#define CLKID_PERIPHS 20
#define CLKID_SPICC 21
#define CLKID_I2C 22
#define CLKID_SAR_ADC 23
+#define CLKID_SMART_CARD 24
#define CLKID_RNG0 25
#define CLKID_UART0 26
+#define CLKID_SDHC 27
+#define CLKID_STREAM 28
+#define CLKID_ASYNC_FIFO 29
+#define CLKID_SDIO 30
+#define CLKID_ABUF 31
+#define CLKID_HIU_IFACE 32
+#define CLKID_ASSIST_MISC 33
#define CLKID_SPI 34
#define CLKID_ETH 36
+#define CLKID_I2S_SPDIF 35
+#define CLKID_DEMUX 37
#define CLKID_AIU_GLUE 38
#define CLKID_IEC958 39
#define CLKID_I2S_OUT 40
+#define CLKID_AMCLK 41
+#define CLKID_AIFIFO2 42
+#define CLKID_MIXER 43
#define CLKID_MIXER_IFACE 44
+#define CLKID_ADC 45
+#define CLKID_BLKMV 46
#define CLKID_AIU 47
#define CLKID_UART1 48
+#define CLKID_G2D 49
#define CLKID_USB0 50
#define CLKID_USB1 51
+#define CLKID_RESET 52
+#define CLKID_NAND 53
+#define CLKID_DOS_PARSER 54
#define CLKID_USB 55
+#define CLKID_VDIN1 56
+#define CLKID_AHB_ARB0 57
+#define CLKID_EFUSE 58
+#define CLKID_BOOT_ROM 59
+#define CLKID_AHB_DATA_BUS 60
+#define CLKID_AHB_CTRL_BUS 61
+#define CLKID_HDMI_INTR_SYNC 62
#define CLKID_HDMI_PCLK 63
#define CLKID_USB1_DDR_BRIDGE 64
#define CLKID_USB0_DDR_BRIDGE 65
+#define CLKID_MMC_PCLK 66
+#define CLKID_DVIN 67
#define CLKID_UART2 68
#define CLKID_SANA 69
+#define CLKID_VPU_INTR 70
+#define CLKID_SEC_AHB_AHB3_BRIDGE 71
+#define CLKID_CLK81_A53 72
+#define CLKID_VCLK2_VENCI0 73
+#define CLKID_VCLK2_VENCI1 74
+#define CLKID_VCLK2_VENCP0 75
+#define CLKID_VCLK2_VENCP1 76
#define CLKID_GCLK_VENCI_INT0 77
+#define CLKID_GCLK_VENCI_INT 78
+#define CLKID_DAC_CLK 79
#define CLKID_AOCLK_GATE 80
#define CLKID_IEC958_GATE 81
+#define CLKID_ENC480P 82
+#define CLKID_RNG1 83
+#define CLKID_GCLK_VENCI_INT1 84
+#define CLKID_VCLK2_VENCLMCC 85
+#define CLKID_VCLK2_VENCL 86
+#define CLKID_VCLK_OTHER 87
+#define CLKID_EDP 88
+#define CLKID_AO_MEDIA_CPU 89
+#define CLKID_AO_AHB_SRAM 90
+#define CLKID_AO_AHB_BUS 91
+#define CLKID_AO_IFACE 92
#define CLKID_AO_I2C 93
#define CLKID_SD_EMMC_A 94
#define CLKID_SD_EMMC_B 95
#define CLKID_CTS_AMCLK 107
#define CLKID_CTS_MCLK_I958 110
#define CLKID_CTS_I958 113
+#define CLKID_32K_CLK 114
+#define CLKID_SD_EMMC_A_CLK0 119
+#define CLKID_SD_EMMC_B_CLK0 122
+#define CLKID_SD_EMMC_C_CLK0 125
+#define CLKID_VPU_0_SEL 126
+#define CLKID_VPU_0 128
+#define CLKID_VPU_1_SEL 129
+#define CLKID_VPU_1 131
+#define CLKID_VPU 132
+#define CLKID_VAPB_0_SEL 133
+#define CLKID_VAPB_0 135
+#define CLKID_VAPB_1_SEL 136
+#define CLKID_VAPB_1 138
+#define CLKID_VAPB_SEL 139
+#define CLKID_VAPB 140
#endif /* __GXBB_CLKC_H */
#define GPIOAO_11 11
#define GPIOAO_12 12
#define GPIOAO_13 13
+#define GPIO_TEST_N 14
#define GPIOZ_0 0
#define GPIOZ_1 1
#define GPIOCLK_1 116
#define GPIOCLK_2 117
#define GPIOCLK_3 118
-#define GPIO_TEST_N 119
#endif
#define GPIOAO_7 7
#define GPIOAO_8 8
#define GPIOAO_9 9
+#define GPIO_TEST_N 10
#define GPIOZ_0 0
#define GPIOZ_1 1
#define GPIOX_18 97
#define GPIOCLK_0 98
#define GPIOCLK_1 99
-#define GPIO_TEST_N 100
#endif
--- /dev/null
+/*
+ * This file is part of stpmu1 pmic driver
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DT_BINDINGS_STPMU1_H__
+#define __DT_BINDINGS_STPMU1_H__
+
+/* IRQ definitions */
+#define IT_PONKEY_F 0
+#define IT_PONKEY_R 1
+#define IT_WAKEUP_F 2
+#define IT_WAKEUP_R 3
+#define IT_VBUS_OTG_F 4
+#define IT_VBUS_OTG_R 5
+#define IT_SWOUT_F 6
+#define IT_SWOUT_R 7
+
+#define IT_CURLIM_BUCK1 8
+#define IT_CURLIM_BUCK2 9
+#define IT_CURLIM_BUCK3 10
+#define IT_CURLIM_BUCK4 11
+#define IT_OCP_OTG 12
+#define IT_OCP_SWOUT 13
+#define IT_OCP_BOOST 14
+#define IT_OVP_BOOST 15
+
+#define IT_CURLIM_LDO1 16
+#define IT_CURLIM_LDO2 17
+#define IT_CURLIM_LDO3 18
+#define IT_CURLIM_LDO4 19
+#define IT_CURLIM_LDO5 20
+#define IT_CURLIM_LDO6 21
+#define IT_SHORT_SWOTG 22
+#define IT_SHORT_SWOUT 23
+
+#define IT_TWARN_F 24
+#define IT_TWARN_R 25
+#define IT_VINLOW_F 26
+#define IT_VINLOW_R 27
+#define IT_SWIN_F 30
+#define IT_SWIN_R 31
+
+#endif /* __DT_BINDINGS_STPMU1_H__ */
"run mmcboot;\0" \
"emmc_android_boot=" \
"echo Trying to boot Android from eMMC ...; " \
+ "run update_to_fit; " \
"setenv eval_bootargs setenv bootargs $bootargs; " \
"run eval_bootargs; " \
"setenv mmcdev 1; " \
"part size mmc ${mmcdev} boot boot_size; " \
"mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; " \
"mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
- "bootm $loadaddr $loadaddr $fdtaddr;\0"
+ "bootm ${loadaddr}#${fdtfile};\0 "
#ifdef CONFIG_OMAP54XX
lbaint_t (*reserve)(struct sparse_storage *info,
lbaint_t blk,
lbaint_t blkcnt);
+
+ void (*mssg)(const char *str);
};
static inline int is_sparse_image(void *buf)
return 0;
}
-void write_sparse_image(struct sparse_storage *info, const char *part_name,
- void *data, unsigned sz);
+int write_sparse_image(struct sparse_storage *info, const char *part_name,
+ void *data);
#define regmap_read32(map, ptr, member, valp) \
regmap_read(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), valp)
+/**
+ * regmap_update_bits() - Perform a read/modify/write using a mask
+ *
+ * @map: The map returned by regmap_init_mem*()
+ * @offset: Offset of the memory
+ * @mask: Mask to apply to the read value
+ * @val: Value to apply to the value to write
+ */
+int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val);
+
/**
* regmap_init_mem() - Set up a new register map that uses memory access
*
};
enum soc_family {
- STM32F4,
+ STM32F42X,
+ STM32F469,
STM32F7,
};
config OF_LIBFDT_OVERLAY
bool "Enable the FDT library overlay support"
+ depends on OF_LIBFDT
+ default y if ARCH_OMAP2PLUS || ARCH_KEYSTONE
help
This enables the FDT library (libfdt) overlay support.
ut_assertok(uclass_get_device(UCLASS_LED, 0, &dev));
ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev));
ut_assertok(uclass_get_device(UCLASS_LED, 2, &dev));
- ut_asserteq(-ENODEV, uclass_get_device(UCLASS_LED, 3, &dev));
+ ut_assertok(uclass_get_device(UCLASS_LED, 3, &dev));
+ ut_assertok(uclass_get_device(UCLASS_LED, 4, &dev));
+ ut_asserteq(-ENODEV, uclass_get_device(UCLASS_LED, 5, &dev));
return 0;
}
DM_TEST(dm_test_led_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+/* Test of the LED 'default-state' device tree property */
+static int dm_test_led_default_state(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ /* Check that we handle the default-state property correctly. */
+ ut_assertok(led_get_by_label("sandbox:default_on", &dev));
+ ut_asserteq(LEDST_ON, led_get_state(dev));
+
+ ut_assertok(led_get_by_label("sandbox:default_off", &dev));
+ ut_asserteq(LEDST_OFF, led_get_state(dev));
+
+ return 0;
+}
+DM_TEST(dm_test_led_default_state, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
/* Test of the led uclass using the led_gpio driver */
static int dm_test_led_gpio(struct unit_test_state *uts)
{
}
DM_TEST(dm_test_regmap_syscon, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Read/Write/Modify test */
+static int dm_test_regmap_rw(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct regmap *map;
+ uint reg;
+
+ ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev));
+ map = syscon_get_regmap(dev);
+ ut_assertok_ptr(map);
+
+ ut_assertok(regmap_write(map, 0, 0xcacafafa));
+ ut_assertok(regmap_write(map, 3, 0x55aa2211));
+
+ ut_assertok(regmap_read(map, 0, ®));
+ ut_assertok(regmap_read(map, 3, ®));
+
+ ut_assertok(regmap_update_bits(map, 0, 0xff00ff00, 0x55aa2211));
+ ut_assertok(regmap_update_bits(map, 3, 0x00ff00ff, 0xcacafada));
+
+ return 0;
+}
+
+DM_TEST(dm_test_regmap_rw, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);