Amlogic driver updates for v4.9, 2nd round

- media: update IR support for newer SoCs
 - firmware: add secure monitor driver
 - net: new stmmac glue driver
 - usb: udd DWC2 support for meson-gxbb
 - clocks: expose more clock IDs for use by DT
 - DT binding updates
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJX2Z0aAAoJEFk3GJrT+8ZlkxoQAI0FJkQ371touZbMRSirMCdG
 fyx7ZZWGntw9yHCqcfVGLxy6oBk6bABWOWJzqGIBeTyn7qDoOqc4ec+pIWg7KECS
 h/yrJLGPQofI0Hm/6nzZikrjrK1h74c6bhkjRsAfqKCyq0AcEnH8cu1kAZmkwyJq
 osU1U/MhRLkIs6UZsc6H2nlsbSw8Ji4ZkSDfT/1P4SUqHgtz9k5PNYCEkPDGK23F
 1f1N3zYpqJVqAqucdLhTBsE56vSVzrAXLEsIwpaYCpEzuRO8MyjYP7SiKnky/5Za
 WAxz+hKufleqvvDqIK1zWvE/in4SyHrg9eVSHac/xbbDsUKy11RuJ2VasqT6xUOM
 r8oi0o1ot0IkMCJrA1Ogey0GqcSoyVUzy5FM+4SOz+M7IctLt7ZV0aVDmfXvG21f
 iQLZ7bPmgaj2kck95ppqc8saz0EIt32fJBaI3XvoG9PTpQeoYI7vok2k1l06kYQI
 3U6r7Zui4mj9PE2aFAEe3BpY2EbJDj8Vn+mtX4NtkCwS0PwZKkiUgZXF3H/qix3T
 +jv9yps2dLhihd4y6RcySVM3/PWuM7A8tU9oRBE+sttf2MiQzXvMPNM/GH0qOVEI
 3flZ6tsSLmj8jmFyOdqaxz8MuDo9KNi9b+AijPqWm+D0UfPPqFKnR6bvM4F496Dx
 4fG2a7JtDJUAz8e++Jtc
 =DlpW
 -----END PGP SIGNATURE-----

Merge tag 'amlogic-drivers-2' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic into next/late

Pull "Amlogic driver updates for v4.9, 2nd round" from Kevin Hilman:

- media: update IR support for newer SoCs
- firmware: add secure monitor driver
- net: new stmmac glue driver
- usb: udd DWC2 support for meson-gxbb
- clocks: expose more clock IDs for use by DT
- DT binding updates

* tag 'amlogic-drivers-2' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic: (21 commits)
  clk: gxbb: expose i2c clocks
  clk: gxbb: expose USB clocks
  clk: gxbb: expose spifc clock
  clk: gxbb: expose MPLL2 clock for use by DT
  Documentation: dt-bindings: Add documentation for the Meson USB2 PHYs
  usb: dwc2: add support for Meson8b and GXBB SoCs
  net: stmmac: update the module description of the dwmac-meson driver
  net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
  stmmac: introduce get_stmmac_bsp_priv() helper
  net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
  clk: meson-gxbb: Export PWM related clocks for DT
  meson: clk: Add support for clock gates
  gxbb: clk: Adjust MESON_GATE macro to be shared with meson8b
  clk: meson: Copy meson8b CLKID defines to private header file
  meson: clk: Rename register names according to Amlogic datasheet
  meson: clk: Move register definitions to meson8b.h
  clk: meson: Rename meson8b-clkc.c to reflect gxbb naming convention
  nvmem: amlogic: Add Amlogic Meson EFUSE driver
  firmware: Amlogic: Add secure monitor driver
  media: rc: meson-ir: Add support for newer versions of the IR decoder
  ...
This commit is contained in:
Arnd Bergmann 2016-09-19 17:49:07 +02:00
commit 53570cbc18
27 changed files with 1394 additions and 145 deletions

View file

@ -1,18 +1,32 @@
* Amlogic Meson DWMAC Ethernet controller
The device inherits all the properties of the dwmac/stmmac devices
described in the file net/stmmac.txt with the following changes.
described in the file stmmac.txt in the current directory with the
following changes.
Required properties:
Required properties on all platforms:
- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"
and any applicable more detailed version number
described in net/stmmac.txt
- compatible: Depending on the platform this should be one of:
- "amlogic,meson6-dwmac"
- "amlogic,meson8b-dwmac"
- "amlogic,meson-gxbb-dwmac"
Additionally "snps,dwmac" and any applicable more
detailed version number described in net/stmmac.txt
should be used.
- reg: should contain a register range for the dwmac controller and
another one for the Amlogic specific configuration
- reg: The first register range should be the one of the DWMAC
controller. The second range is is for the Amlogic specific
configuration (for example the PRG_ETHERNET register range
on Meson8b and newer)
Example:
Required properties on Meson8b and newer:
- clock-names: Should contain the following:
- "stmmaceth" - see stmmac.txt
- "clkin0" - first parent clock of the internal mux
- "clkin1" - second parent clock of the internal mux
Example for Meson6:
ethmac: ethernet@c9410000 {
compatible = "amlogic,meson6-dwmac", "snps,dwmac";
@ -23,3 +37,18 @@ Example:
clocks = <&clk81>;
clock-names = "stmmaceth";
}
Example for GXBB:
ethmac: ethernet@c9410000 {
compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
reg = <0x0 0xc9410000 0x0 0x10000>,
<0x0 0xc8834540 0x0 0x8>;
interrupts = <0 8 1>;
interrupt-names = "macirq";
clocks = <&clkc CLKID_ETH>,
<&clkc CLKID_FCLK_DIV2>,
<&clkc CLKID_MPLL2>;
clock-names = "stmmaceth", "clkin0", "clkin1";
phy-mode = "rgmii";
status = "disabled";
};

View file

@ -0,0 +1,27 @@
* Amlogic USB2 PHY
Required properties:
- compatible: Depending on the platform this should be one of:
"amlogic,meson8b-usb2-phy"
"amlogic,meson-gxbb-usb2-phy"
- reg: The base address and length of the registers
- #phys-cells: should be 0 (see phy-bindings.txt in this directory)
- clocks: phandle and clock identifier for the phy clocks
- clock-names: "usb_general" and "usb"
Optional properties:
- resets: reference to the reset controller
- phy-supply: see phy-bindings.txt in this directory
Example:
usb0_phy: usb_phy@0 {
compatible = "amlogic,meson-gxbb-usb2-phy";
#phy-cells = <0>;
reg = <0x0 0x0 0x0 0x20>;
resets = <&reset RESET_USB_OTG>;
clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
clock-names = "usb_general", "usb";
phy-supply = <&usb_vbus>;
};

View file

@ -10,6 +10,8 @@ Required properties:
- "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc;
- "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs;
- "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs;
- "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs;
- "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
- snps,dwc2: A generic DWC2 USB controller with default parameters.
- reg : Should contain 1 register range (address and length)
- interrupts : Should contain 1 interrupt

View file

@ -3,5 +3,5 @@
#
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o

View file

@ -98,7 +98,7 @@ struct meson_clk_mpll {
};
#define MESON_GATE(_name, _reg, _bit) \
struct clk_gate gxbb_##_name = { \
struct clk_gate _name = { \
.reg = (void __iomem *) _reg, \
.bit_idx = (_bit), \
.lock = &clk_lock, \

View file

@ -565,90 +565,93 @@ static struct clk_gate gxbb_clk81 = {
};
/* Everything Else (EE) domain gates */
static MESON_GATE(ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(dos, HHI_GCLK_MPEG0, 1);
static MESON_GATE(isa, HHI_GCLK_MPEG0, 5);
static MESON_GATE(pl301, HHI_GCLK_MPEG0, 6);
static MESON_GATE(periphs, HHI_GCLK_MPEG0, 7);
static MESON_GATE(spicc, HHI_GCLK_MPEG0, 8);
static MESON_GATE(i2c, HHI_GCLK_MPEG0, 9);
static MESON_GATE(sar_adc, HHI_GCLK_MPEG0, 10);
static MESON_GATE(smart_card, HHI_GCLK_MPEG0, 11);
static MESON_GATE(rng0, HHI_GCLK_MPEG0, 12);
static MESON_GATE(uart0, HHI_GCLK_MPEG0, 13);
static MESON_GATE(sdhc, HHI_GCLK_MPEG0, 14);
static MESON_GATE(stream, HHI_GCLK_MPEG0, 15);
static MESON_GATE(async_fifo, HHI_GCLK_MPEG0, 16);
static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17);
static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18);
static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19);
static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23);
static MESON_GATE(spi, HHI_GCLK_MPEG0, 30);
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
static MESON_GATE(gxbb_isa, HHI_GCLK_MPEG0, 5);
static MESON_GATE(gxbb_pl301, HHI_GCLK_MPEG0, 6);
static MESON_GATE(gxbb_periphs, HHI_GCLK_MPEG0, 7);
static MESON_GATE(gxbb_spicc, HHI_GCLK_MPEG0, 8);
static MESON_GATE(gxbb_i2c, HHI_GCLK_MPEG0, 9);
static MESON_GATE(gxbb_sar_adc, HHI_GCLK_MPEG0, 10);
static MESON_GATE(gxbb_smart_card, HHI_GCLK_MPEG0, 11);
static MESON_GATE(gxbb_rng0, HHI_GCLK_MPEG0, 12);
static MESON_GATE(gxbb_uart0, HHI_GCLK_MPEG0, 13);
static MESON_GATE(gxbb_sdhc, HHI_GCLK_MPEG0, 14);
static MESON_GATE(gxbb_stream, HHI_GCLK_MPEG0, 15);
static MESON_GATE(gxbb_async_fifo, HHI_GCLK_MPEG0, 16);
static MESON_GATE(gxbb_sdio, HHI_GCLK_MPEG0, 17);
static MESON_GATE(gxbb_abuf, HHI_GCLK_MPEG0, 18);
static MESON_GATE(gxbb_hiu_iface, HHI_GCLK_MPEG0, 19);
static MESON_GATE(gxbb_assist_misc, HHI_GCLK_MPEG0, 23);
static MESON_GATE(gxbb_emmc_a, HHI_GCLK_MPEG0, 24);
static MESON_GATE(gxbb_emmc_b, HHI_GCLK_MPEG0, 25);
static MESON_GATE(gxbb_emmc_c, HHI_GCLK_MPEG0, 26);
static MESON_GATE(gxbb_spi, HHI_GCLK_MPEG0, 30);
static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2);
static MESON_GATE(eth, HHI_GCLK_MPEG1, 3);
static MESON_GATE(demux, HHI_GCLK_MPEG1, 4);
static MESON_GATE(aiu_glue, HHI_GCLK_MPEG1, 6);
static MESON_GATE(iec958, HHI_GCLK_MPEG1, 7);
static MESON_GATE(i2s_out, HHI_GCLK_MPEG1, 8);
static MESON_GATE(amclk, HHI_GCLK_MPEG1, 9);
static MESON_GATE(aififo2, HHI_GCLK_MPEG1, 10);
static MESON_GATE(mixer, HHI_GCLK_MPEG1, 11);
static MESON_GATE(mixer_iface, HHI_GCLK_MPEG1, 12);
static MESON_GATE(adc, HHI_GCLK_MPEG1, 13);
static MESON_GATE(blkmv, HHI_GCLK_MPEG1, 14);
static MESON_GATE(aiu, HHI_GCLK_MPEG1, 15);
static MESON_GATE(uart1, HHI_GCLK_MPEG1, 16);
static MESON_GATE(g2d, HHI_GCLK_MPEG1, 20);
static MESON_GATE(usb0, HHI_GCLK_MPEG1, 21);
static MESON_GATE(usb1, HHI_GCLK_MPEG1, 22);
static MESON_GATE(reset, HHI_GCLK_MPEG1, 23);
static MESON_GATE(nand, HHI_GCLK_MPEG1, 24);
static MESON_GATE(dos_parser, HHI_GCLK_MPEG1, 25);
static MESON_GATE(usb, HHI_GCLK_MPEG1, 26);
static MESON_GATE(vdin1, HHI_GCLK_MPEG1, 28);
static MESON_GATE(ahb_arb0, HHI_GCLK_MPEG1, 29);
static MESON_GATE(efuse, HHI_GCLK_MPEG1, 30);
static MESON_GATE(boot_rom, HHI_GCLK_MPEG1, 31);
static MESON_GATE(gxbb_i2s_spdif, HHI_GCLK_MPEG1, 2);
static MESON_GATE(gxbb_eth, HHI_GCLK_MPEG1, 3);
static MESON_GATE(gxbb_demux, HHI_GCLK_MPEG1, 4);
static MESON_GATE(gxbb_aiu_glue, HHI_GCLK_MPEG1, 6);
static MESON_GATE(gxbb_iec958, HHI_GCLK_MPEG1, 7);
static MESON_GATE(gxbb_i2s_out, HHI_GCLK_MPEG1, 8);
static MESON_GATE(gxbb_amclk, HHI_GCLK_MPEG1, 9);
static MESON_GATE(gxbb_aififo2, HHI_GCLK_MPEG1, 10);
static MESON_GATE(gxbb_mixer, HHI_GCLK_MPEG1, 11);
static MESON_GATE(gxbb_mixer_iface, HHI_GCLK_MPEG1, 12);
static MESON_GATE(gxbb_adc, HHI_GCLK_MPEG1, 13);
static MESON_GATE(gxbb_blkmv, HHI_GCLK_MPEG1, 14);
static MESON_GATE(gxbb_aiu, HHI_GCLK_MPEG1, 15);
static MESON_GATE(gxbb_uart1, HHI_GCLK_MPEG1, 16);
static MESON_GATE(gxbb_g2d, HHI_GCLK_MPEG1, 20);
static MESON_GATE(gxbb_usb0, HHI_GCLK_MPEG1, 21);
static MESON_GATE(gxbb_usb1, HHI_GCLK_MPEG1, 22);
static MESON_GATE(gxbb_reset, HHI_GCLK_MPEG1, 23);
static MESON_GATE(gxbb_nand, HHI_GCLK_MPEG1, 24);
static MESON_GATE(gxbb_dos_parser, HHI_GCLK_MPEG1, 25);
static MESON_GATE(gxbb_usb, HHI_GCLK_MPEG1, 26);
static MESON_GATE(gxbb_vdin1, HHI_GCLK_MPEG1, 28);
static MESON_GATE(gxbb_ahb_arb0, HHI_GCLK_MPEG1, 29);
static MESON_GATE(gxbb_efuse, HHI_GCLK_MPEG1, 30);
static MESON_GATE(gxbb_boot_rom, HHI_GCLK_MPEG1, 31);
static MESON_GATE(ahb_data_bus, HHI_GCLK_MPEG2, 1);
static MESON_GATE(ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
static MESON_GATE(hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
static MESON_GATE(hdmi_pclk, HHI_GCLK_MPEG2, 4);
static MESON_GATE(usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
static MESON_GATE(usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
static MESON_GATE(mmc_pclk, HHI_GCLK_MPEG2, 11);
static MESON_GATE(dvin, HHI_GCLK_MPEG2, 12);
static MESON_GATE(uart2, HHI_GCLK_MPEG2, 15);
static MESON_GATE(sana, HHI_GCLK_MPEG2, 22);
static MESON_GATE(vpu_intr, HHI_GCLK_MPEG2, 25);
static MESON_GATE(sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
static MESON_GATE(clk81_a53, HHI_GCLK_MPEG2, 29);
static MESON_GATE(gxbb_ahb_data_bus, HHI_GCLK_MPEG2, 1);
static MESON_GATE(gxbb_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
static MESON_GATE(gxbb_hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
static MESON_GATE(gxbb_hdmi_pclk, HHI_GCLK_MPEG2, 4);
static MESON_GATE(gxbb_usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
static MESON_GATE(gxbb_usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
static MESON_GATE(gxbb_mmc_pclk, HHI_GCLK_MPEG2, 11);
static MESON_GATE(gxbb_dvin, HHI_GCLK_MPEG2, 12);
static MESON_GATE(gxbb_uart2, HHI_GCLK_MPEG2, 15);
static MESON_GATE(gxbb_sana, HHI_GCLK_MPEG2, 22);
static MESON_GATE(gxbb_vpu_intr, HHI_GCLK_MPEG2, 25);
static MESON_GATE(gxbb_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
static MESON_GATE(gxbb_clk81_a53, HHI_GCLK_MPEG2, 29);
static MESON_GATE(vclk2_venci0, HHI_GCLK_OTHER, 1);
static MESON_GATE(vclk2_venci1, HHI_GCLK_OTHER, 2);
static MESON_GATE(vclk2_vencp0, HHI_GCLK_OTHER, 3);
static MESON_GATE(vclk2_vencp1, HHI_GCLK_OTHER, 4);
static MESON_GATE(gclk_venci_int0, HHI_GCLK_OTHER, 8);
static MESON_GATE(gclk_vencp_int, HHI_GCLK_OTHER, 9);
static MESON_GATE(dac_clk, HHI_GCLK_OTHER, 10);
static MESON_GATE(aoclk_gate, HHI_GCLK_OTHER, 14);
static MESON_GATE(iec958_gate, HHI_GCLK_OTHER, 16);
static MESON_GATE(enc480p, HHI_GCLK_OTHER, 20);
static MESON_GATE(rng1, HHI_GCLK_OTHER, 21);
static MESON_GATE(gclk_venci_int1, HHI_GCLK_OTHER, 22);
static MESON_GATE(vclk2_venclmcc, HHI_GCLK_OTHER, 24);
static MESON_GATE(vclk2_vencl, HHI_GCLK_OTHER, 25);
static MESON_GATE(vclk_other, HHI_GCLK_OTHER, 26);
static MESON_GATE(edp, HHI_GCLK_OTHER, 31);
static MESON_GATE(gxbb_vclk2_venci0, HHI_GCLK_OTHER, 1);
static MESON_GATE(gxbb_vclk2_venci1, HHI_GCLK_OTHER, 2);
static MESON_GATE(gxbb_vclk2_vencp0, HHI_GCLK_OTHER, 3);
static MESON_GATE(gxbb_vclk2_vencp1, HHI_GCLK_OTHER, 4);
static MESON_GATE(gxbb_gclk_venci_int0, HHI_GCLK_OTHER, 8);
static MESON_GATE(gxbb_gclk_vencp_int, HHI_GCLK_OTHER, 9);
static MESON_GATE(gxbb_dac_clk, HHI_GCLK_OTHER, 10);
static MESON_GATE(gxbb_aoclk_gate, HHI_GCLK_OTHER, 14);
static MESON_GATE(gxbb_iec958_gate, HHI_GCLK_OTHER, 16);
static MESON_GATE(gxbb_enc480p, HHI_GCLK_OTHER, 20);
static MESON_GATE(gxbb_rng1, HHI_GCLK_OTHER, 21);
static MESON_GATE(gxbb_gclk_venci_int1, HHI_GCLK_OTHER, 22);
static MESON_GATE(gxbb_vclk2_venclmcc, HHI_GCLK_OTHER, 24);
static MESON_GATE(gxbb_vclk2_vencl, HHI_GCLK_OTHER, 25);
static MESON_GATE(gxbb_vclk_other, HHI_GCLK_OTHER, 26);
static MESON_GATE(gxbb_edp, HHI_GCLK_OTHER, 31);
/* Always On (AO) domain gates */
static MESON_GATE(ao_media_cpu, HHI_GCLK_AO, 0);
static MESON_GATE(ao_ahb_sram, HHI_GCLK_AO, 1);
static MESON_GATE(ao_ahb_bus, HHI_GCLK_AO, 2);
static MESON_GATE(ao_iface, HHI_GCLK_AO, 3);
static MESON_GATE(ao_i2c, HHI_GCLK_AO, 4);
static MESON_GATE(gxbb_ao_media_cpu, HHI_GCLK_AO, 0);
static MESON_GATE(gxbb_ao_ahb_sram, HHI_GCLK_AO, 1);
static MESON_GATE(gxbb_ao_ahb_bus, HHI_GCLK_AO, 2);
static MESON_GATE(gxbb_ao_iface, HHI_GCLK_AO, 3);
static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4);
/* Array of all clocks provided by this provider */
@ -748,6 +751,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_AO_AHB_BUS] = &gxbb_ao_ahb_bus.hw,
[CLKID_AO_IFACE] = &gxbb_ao_iface.hw,
[CLKID_AO_I2C] = &gxbb_ao_i2c.hw,
[CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw,
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
},
.num = NR_CLKS,
};
@ -847,6 +853,9 @@ static struct clk_gate *gxbb_clk_gates[] = {
&gxbb_ao_ahb_bus,
&gxbb_ao_iface,
&gxbb_ao_i2c,
&gxbb_emmc_a,
&gxbb_emmc_b,
&gxbb_emmc_c,
};
static int gxbb_clkc_probe(struct platform_device *pdev)

View file

@ -170,11 +170,11 @@
*/
#define CLKID_SYS_PLL 0
/* CLKID_CPUCLK */
#define CLKID_HDMI_PLL 2
/* CLKID_HDMI_PLL */
#define CLKID_FIXED_PLL 3
#define CLKID_FCLK_DIV2 4
#define CLKID_FCLK_DIV3 5
#define CLKID_FCLK_DIV4 6
/* CLKID_FCLK_DIV2 */
/* CLKID_FCLK_DIV3 */
/* CLKID_FCLK_DIV4 */
#define CLKID_FCLK_DIV5 7
#define CLKID_FCLK_DIV7 8
#define CLKID_GP0_PLL 9
@ -183,14 +183,14 @@
/* CLKID_CLK81 */
#define CLKID_MPLL0 13
#define CLKID_MPLL1 14
#define CLKID_MPLL2 15
/* CLKID_MPLL2 */
#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
/* CLKID_I2C */
#define CLKID_SAR_ADC 23
#define CLKID_SMART_CARD 24
#define CLKID_RNG0 25
@ -202,7 +202,7 @@
#define CLKID_ABUF 31
#define CLKID_HIU_IFACE 32
#define CLKID_ASSIST_MISC 33
#define CLKID_SPI 34
/* CLKID_SPI */
#define CLKID_I2S_SPDIF 35
#define CLKID_ETH 36
#define CLKID_DEMUX 37
@ -218,12 +218,12 @@
#define CLKID_AIU 47
#define CLKID_UART1 48
#define CLKID_G2D 49
#define CLKID_USB0 50
#define CLKID_USB1 51
/* CLKID_USB0 */
/* CLKID_USB1 */
#define CLKID_RESET 52
#define CLKID_NAND 53
#define CLKID_DOS_PARSER 54
#define CLKID_USB 55
/* CLKID_USB */
#define CLKID_VDIN1 56
#define CLKID_AHB_ARB0 57
#define CLKID_EFUSE 58
@ -232,8 +232,8 @@
#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
/* CLKID_USB1_DDR_BRIDGE */
/* CLKID_USB0_DDR_BRIDGE */
#define CLKID_MMC_PCLK 66
#define CLKID_DVIN 67
#define CLKID_UART2 68
@ -261,9 +261,12 @@
#define CLKID_AO_AHB_SRAM 90
#define CLKID_AO_AHB_BUS 91
#define CLKID_AO_IFACE 92
#define CLKID_AO_I2C 93
/* CLKID_AO_I2C */
/* CLKID_SD_EMMC_A */
/* CLKID_SD_EMMC_B */
/* CLKID_SD_EMMC_C */
#define NR_CLKS 94
#define NR_CLKS 97
/* include the CLKIDs that have been made part of the stable DT binding */
#include <dt-bindings/clock/gxbb-clkc.h>

View file

@ -23,27 +23,11 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/meson8b-clkc.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include "clkc.h"
/*
* Clock controller register offsets
*
* Register offsets from the HardKernel[0] data sheet are listed in comment
* blocks below. Those offsets must be multiplied by 4 before adding them to
* the base address to get the right value
*
* [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
*/
#define MESON8B_REG_SYS_CPU_CNTL1 0x015c /* 0x57 offset in data sheet */
#define MESON8B_REG_HHI_MPEG 0x0174 /* 0x5d offset in data sheet */
#define MESON8B_REG_MALI 0x01b0 /* 0x6c offset in data sheet */
#define MESON8B_REG_PLL_FIXED 0x0280
#define MESON8B_REG_PLL_SYS 0x0300
#define MESON8B_REG_PLL_VID 0x0320
#include "meson8b.h"
static DEFINE_SPINLOCK(clk_lock);
@ -128,17 +112,17 @@ static struct clk_fixed_rate meson8b_xtal = {
static struct meson_clk_pll meson8b_fixed_pll = {
.m = {
.reg_off = MESON8B_REG_PLL_FIXED,
.reg_off = HHI_MPLL_CNTL,
.shift = 0,
.width = 9,
},
.n = {
.reg_off = MESON8B_REG_PLL_FIXED,
.reg_off = HHI_MPLL_CNTL,
.shift = 9,
.width = 5,
},
.od = {
.reg_off = MESON8B_REG_PLL_FIXED,
.reg_off = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
},
@ -154,17 +138,17 @@ static struct meson_clk_pll meson8b_fixed_pll = {
static struct meson_clk_pll meson8b_vid_pll = {
.m = {
.reg_off = MESON8B_REG_PLL_VID,
.reg_off = HHI_VID_PLL_CNTL,
.shift = 0,
.width = 9,
},
.n = {
.reg_off = MESON8B_REG_PLL_VID,
.reg_off = HHI_VID_PLL_CNTL,
.shift = 9,
.width = 5,
},
.od = {
.reg_off = MESON8B_REG_PLL_VID,
.reg_off = HHI_VID_PLL_CNTL,
.shift = 16,
.width = 2,
},
@ -180,17 +164,17 @@ static struct meson_clk_pll meson8b_vid_pll = {
static struct meson_clk_pll meson8b_sys_pll = {
.m = {
.reg_off = MESON8B_REG_PLL_SYS,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
.width = 9,
},
.n = {
.reg_off = MESON8B_REG_PLL_SYS,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 9,
.width = 5,
},
.od = {
.reg_off = MESON8B_REG_PLL_SYS,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 16,
.width = 2,
},
@ -267,7 +251,7 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
* forthcoming coordinated clock rates feature
*/
static struct meson_clk_cpu meson8b_cpu_clk = {
.reg_off = MESON8B_REG_SYS_CPU_CNTL1,
.reg_off = HHI_SYS_CPU_CLK_CNTL1,
.div_table = cpu_div_table,
.clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
.hw.init = &(struct clk_init_data){
@ -281,7 +265,7 @@ static struct meson_clk_cpu meson8b_cpu_clk = {
static u32 mux_table_clk81[] = { 6, 5, 7 };
struct clk_mux meson8b_mpeg_clk_sel = {
.reg = (void *)MESON8B_REG_HHI_MPEG,
.reg = (void *)HHI_MPEG_CLK_CNTL,
.mask = 0x7,
.shift = 12,
.flags = CLK_MUX_READ_ONLY,
@ -303,7 +287,7 @@ struct clk_mux meson8b_mpeg_clk_sel = {
};
struct clk_divider meson8b_mpeg_clk_div = {
.reg = (void *)MESON8B_REG_HHI_MPEG,
.reg = (void *)HHI_MPEG_CLK_CNTL,
.shift = 0,
.width = 7,
.lock = &clk_lock,
@ -317,7 +301,7 @@ struct clk_divider meson8b_mpeg_clk_div = {
};
struct clk_gate meson8b_clk81 = {
.reg = (void *)MESON8B_REG_HHI_MPEG,
.reg = (void *)HHI_MPEG_CLK_CNTL,
.bit_idx = 7,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
@ -329,6 +313,92 @@ struct clk_gate meson8b_clk81 = {
},
};
/* Everything Else (EE) domain gates */
static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(meson8b_dos, HHI_GCLK_MPEG0, 1);
static MESON_GATE(meson8b_isa, HHI_GCLK_MPEG0, 5);
static MESON_GATE(meson8b_pl301, HHI_GCLK_MPEG0, 6);
static MESON_GATE(meson8b_periphs, HHI_GCLK_MPEG0, 7);
static MESON_GATE(meson8b_spicc, HHI_GCLK_MPEG0, 8);
static MESON_GATE(meson8b_i2c, HHI_GCLK_MPEG0, 9);
static MESON_GATE(meson8b_sar_adc, HHI_GCLK_MPEG0, 10);
static MESON_GATE(meson8b_smart_card, HHI_GCLK_MPEG0, 11);
static MESON_GATE(meson8b_rng0, HHI_GCLK_MPEG0, 12);
static MESON_GATE(meson8b_uart0, HHI_GCLK_MPEG0, 13);
static MESON_GATE(meson8b_sdhc, HHI_GCLK_MPEG0, 14);
static MESON_GATE(meson8b_stream, HHI_GCLK_MPEG0, 15);
static MESON_GATE(meson8b_async_fifo, HHI_GCLK_MPEG0, 16);
static MESON_GATE(meson8b_sdio, HHI_GCLK_MPEG0, 17);
static MESON_GATE(meson8b_abuf, HHI_GCLK_MPEG0, 18);
static MESON_GATE(meson8b_hiu_iface, HHI_GCLK_MPEG0, 19);
static MESON_GATE(meson8b_assist_misc, HHI_GCLK_MPEG0, 23);
static MESON_GATE(meson8b_spi, HHI_GCLK_MPEG0, 30);
static MESON_GATE(meson8b_i2s_spdif, HHI_GCLK_MPEG1, 2);
static MESON_GATE(meson8b_eth, HHI_GCLK_MPEG1, 3);
static MESON_GATE(meson8b_demux, HHI_GCLK_MPEG1, 4);
static MESON_GATE(meson8b_aiu_glue, HHI_GCLK_MPEG1, 6);
static MESON_GATE(meson8b_iec958, HHI_GCLK_MPEG1, 7);
static MESON_GATE(meson8b_i2s_out, HHI_GCLK_MPEG1, 8);
static MESON_GATE(meson8b_amclk, HHI_GCLK_MPEG1, 9);
static MESON_GATE(meson8b_aififo2, HHI_GCLK_MPEG1, 10);
static MESON_GATE(meson8b_mixer, HHI_GCLK_MPEG1, 11);
static MESON_GATE(meson8b_mixer_iface, HHI_GCLK_MPEG1, 12);
static MESON_GATE(meson8b_adc, HHI_GCLK_MPEG1, 13);
static MESON_GATE(meson8b_blkmv, HHI_GCLK_MPEG1, 14);
static MESON_GATE(meson8b_aiu, HHI_GCLK_MPEG1, 15);
static MESON_GATE(meson8b_uart1, HHI_GCLK_MPEG1, 16);
static MESON_GATE(meson8b_g2d, HHI_GCLK_MPEG1, 20);
static MESON_GATE(meson8b_usb0, HHI_GCLK_MPEG1, 21);
static MESON_GATE(meson8b_usb1, HHI_GCLK_MPEG1, 22);
static MESON_GATE(meson8b_reset, HHI_GCLK_MPEG1, 23);
static MESON_GATE(meson8b_nand, HHI_GCLK_MPEG1, 24);
static MESON_GATE(meson8b_dos_parser, HHI_GCLK_MPEG1, 25);
static MESON_GATE(meson8b_usb, HHI_GCLK_MPEG1, 26);
static MESON_GATE(meson8b_vdin1, HHI_GCLK_MPEG1, 28);
static MESON_GATE(meson8b_ahb_arb0, HHI_GCLK_MPEG1, 29);
static MESON_GATE(meson8b_efuse, HHI_GCLK_MPEG1, 30);
static MESON_GATE(meson8b_boot_rom, HHI_GCLK_MPEG1, 31);
static MESON_GATE(meson8b_ahb_data_bus, HHI_GCLK_MPEG2, 1);
static MESON_GATE(meson8b_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
static MESON_GATE(meson8b_hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
static MESON_GATE(meson8b_hdmi_pclk, HHI_GCLK_MPEG2, 4);
static MESON_GATE(meson8b_usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
static MESON_GATE(meson8b_usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
static MESON_GATE(meson8b_mmc_pclk, HHI_GCLK_MPEG2, 11);
static MESON_GATE(meson8b_dvin, HHI_GCLK_MPEG2, 12);
static MESON_GATE(meson8b_uart2, HHI_GCLK_MPEG2, 15);
static MESON_GATE(meson8b_sana, HHI_GCLK_MPEG2, 22);
static MESON_GATE(meson8b_vpu_intr, HHI_GCLK_MPEG2, 25);
static MESON_GATE(meson8b_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
static MESON_GATE(meson8b_clk81_a9, HHI_GCLK_MPEG2, 29);
static MESON_GATE(meson8b_vclk2_venci0, HHI_GCLK_OTHER, 1);
static MESON_GATE(meson8b_vclk2_venci1, HHI_GCLK_OTHER, 2);
static MESON_GATE(meson8b_vclk2_vencp0, HHI_GCLK_OTHER, 3);
static MESON_GATE(meson8b_vclk2_vencp1, HHI_GCLK_OTHER, 4);
static MESON_GATE(meson8b_gclk_venci_int, HHI_GCLK_OTHER, 8);
static MESON_GATE(meson8b_gclk_vencp_int, HHI_GCLK_OTHER, 9);
static MESON_GATE(meson8b_dac_clk, HHI_GCLK_OTHER, 10);
static MESON_GATE(meson8b_aoclk_gate, HHI_GCLK_OTHER, 14);
static MESON_GATE(meson8b_iec958_gate, HHI_GCLK_OTHER, 16);
static MESON_GATE(meson8b_enc480p, HHI_GCLK_OTHER, 20);
static MESON_GATE(meson8b_rng1, HHI_GCLK_OTHER, 21);
static MESON_GATE(meson8b_gclk_vencl_int, HHI_GCLK_OTHER, 22);
static MESON_GATE(meson8b_vclk2_venclmcc, HHI_GCLK_OTHER, 24);
static MESON_GATE(meson8b_vclk2_vencl, HHI_GCLK_OTHER, 25);
static MESON_GATE(meson8b_vclk2_other, HHI_GCLK_OTHER, 26);
static MESON_GATE(meson8b_edp, HHI_GCLK_OTHER, 31);
/* Always On (AO) domain gates */
static MESON_GATE(meson8b_ao_media_cpu, HHI_GCLK_AO, 0);
static MESON_GATE(meson8b_ao_ahb_sram, HHI_GCLK_AO, 1);
static MESON_GATE(meson8b_ao_ahb_bus, HHI_GCLK_AO, 2);
static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3);
static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
.hws = {
[CLKID_XTAL] = &meson8b_xtal.hw,
@ -344,6 +414,83 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw,
[CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw,
[CLKID_CLK81] = &meson8b_clk81.hw,
[CLKID_DDR] = &meson8b_ddr.hw,
[CLKID_DOS] = &meson8b_dos.hw,
[CLKID_ISA] = &meson8b_isa.hw,
[CLKID_PL301] = &meson8b_pl301.hw,
[CLKID_PERIPHS] = &meson8b_periphs.hw,
[CLKID_SPICC] = &meson8b_spicc.hw,
[CLKID_I2C] = &meson8b_i2c.hw,
[CLKID_SAR_ADC] = &meson8b_sar_adc.hw,
[CLKID_SMART_CARD] = &meson8b_smart_card.hw,
[CLKID_RNG0] = &meson8b_rng0.hw,
[CLKID_UART0] = &meson8b_uart0.hw,
[CLKID_SDHC] = &meson8b_sdhc.hw,
[CLKID_STREAM] = &meson8b_stream.hw,
[CLKID_ASYNC_FIFO] = &meson8b_async_fifo.hw,
[CLKID_SDIO] = &meson8b_sdio.hw,
[CLKID_ABUF] = &meson8b_abuf.hw,
[CLKID_HIU_IFACE] = &meson8b_hiu_iface.hw,
[CLKID_ASSIST_MISC] = &meson8b_assist_misc.hw,
[CLKID_SPI] = &meson8b_spi.hw,
[CLKID_I2S_SPDIF] = &meson8b_i2s_spdif.hw,
[CLKID_ETH] = &meson8b_eth.hw,
[CLKID_DEMUX] = &meson8b_demux.hw,
[CLKID_AIU_GLUE] = &meson8b_aiu_glue.hw,
[CLKID_IEC958] = &meson8b_iec958.hw,
[CLKID_I2S_OUT] = &meson8b_i2s_out.hw,
[CLKID_AMCLK] = &meson8b_amclk.hw,
[CLKID_AIFIFO2] = &meson8b_aififo2.hw,
[CLKID_MIXER] = &meson8b_mixer.hw,
[CLKID_MIXER_IFACE] = &meson8b_mixer_iface.hw,
[CLKID_ADC] = &meson8b_adc.hw,
[CLKID_BLKMV] = &meson8b_blkmv.hw,
[CLKID_AIU] = &meson8b_aiu.hw,
[CLKID_UART1] = &meson8b_uart1.hw,
[CLKID_G2D] = &meson8b_g2d.hw,
[CLKID_USB0] = &meson8b_usb0.hw,
[CLKID_USB1] = &meson8b_usb1.hw,
[CLKID_RESET] = &meson8b_reset.hw,
[CLKID_NAND] = &meson8b_nand.hw,
[CLKID_DOS_PARSER] = &meson8b_dos_parser.hw,
[CLKID_USB] = &meson8b_usb.hw,
[CLKID_VDIN1] = &meson8b_vdin1.hw,
[CLKID_AHB_ARB0] = &meson8b_ahb_arb0.hw,
[CLKID_EFUSE] = &meson8b_efuse.hw,
[CLKID_BOOT_ROM] = &meson8b_boot_rom.hw,
[CLKID_AHB_DATA_BUS] = &meson8b_ahb_data_bus.hw,
[CLKID_AHB_CTRL_BUS] = &meson8b_ahb_ctrl_bus.hw,
[CLKID_HDMI_INTR_SYNC] = &meson8b_hdmi_intr_sync.hw,
[CLKID_HDMI_PCLK] = &meson8b_hdmi_pclk.hw,
[CLKID_USB1_DDR_BRIDGE] = &meson8b_usb1_ddr_bridge.hw,
[CLKID_USB0_DDR_BRIDGE] = &meson8b_usb0_ddr_bridge.hw,
[CLKID_MMC_PCLK] = &meson8b_mmc_pclk.hw,
[CLKID_DVIN] = &meson8b_dvin.hw,
[CLKID_UART2] = &meson8b_uart2.hw,
[CLKID_SANA] = &meson8b_sana.hw,
[CLKID_VPU_INTR] = &meson8b_vpu_intr.hw,
[CLKID_SEC_AHB_AHB3_BRIDGE] = &meson8b_sec_ahb_ahb3_bridge.hw,
[CLKID_CLK81_A9] = &meson8b_clk81_a9.hw,
[CLKID_VCLK2_VENCI0] = &meson8b_vclk2_venci0.hw,
[CLKID_VCLK2_VENCI1] = &meson8b_vclk2_venci1.hw,
[CLKID_VCLK2_VENCP0] = &meson8b_vclk2_vencp0.hw,
[CLKID_VCLK2_VENCP1] = &meson8b_vclk2_vencp1.hw,
[CLKID_GCLK_VENCI_INT] = &meson8b_gclk_venci_int.hw,
[CLKID_GCLK_VENCI_INT] = &meson8b_gclk_vencp_int.hw,
[CLKID_DAC_CLK] = &meson8b_dac_clk.hw,
[CLKID_AOCLK_GATE] = &meson8b_aoclk_gate.hw,
[CLKID_IEC958_GATE] = &meson8b_iec958_gate.hw,
[CLKID_ENC480P] = &meson8b_enc480p.hw,
[CLKID_RNG1] = &meson8b_rng1.hw,
[CLKID_GCLK_VENCL_INT] = &meson8b_gclk_vencl_int.hw,
[CLKID_VCLK2_VENCLMCC] = &meson8b_vclk2_venclmcc.hw,
[CLKID_VCLK2_VENCL] = &meson8b_vclk2_vencl.hw,
[CLKID_VCLK2_OTHER] = &meson8b_vclk2_other.hw,
[CLKID_EDP] = &meson8b_edp.hw,
[CLKID_AO_MEDIA_CPU] = &meson8b_ao_media_cpu.hw,
[CLKID_AO_AHB_SRAM] = &meson8b_ao_ahb_sram.hw,
[CLKID_AO_AHB_BUS] = &meson8b_ao_ahb_bus.hw,
[CLKID_AO_IFACE] = &meson8b_ao_iface.hw,
},
.num = CLK_NR_CLKS,
};
@ -354,6 +501,87 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
&meson8b_sys_pll,
};
static struct clk_gate *meson8b_clk_gates[] = {
&meson8b_clk81,
&meson8b_ddr,
&meson8b_dos,
&meson8b_isa,
&meson8b_pl301,
&meson8b_periphs,
&meson8b_spicc,
&meson8b_i2c,
&meson8b_sar_adc,
&meson8b_smart_card,
&meson8b_rng0,
&meson8b_uart0,
&meson8b_sdhc,
&meson8b_stream,
&meson8b_async_fifo,
&meson8b_sdio,
&meson8b_abuf,
&meson8b_hiu_iface,
&meson8b_assist_misc,
&meson8b_spi,
&meson8b_i2s_spdif,
&meson8b_eth,
&meson8b_demux,
&meson8b_aiu_glue,
&meson8b_iec958,
&meson8b_i2s_out,
&meson8b_amclk,
&meson8b_aififo2,
&meson8b_mixer,
&meson8b_mixer_iface,
&meson8b_adc,
&meson8b_blkmv,
&meson8b_aiu,
&meson8b_uart1,
&meson8b_g2d,
&meson8b_usb0,
&meson8b_usb1,
&meson8b_reset,
&meson8b_nand,
&meson8b_dos_parser,
&meson8b_usb,
&meson8b_vdin1,
&meson8b_ahb_arb0,
&meson8b_efuse,
&meson8b_boot_rom,
&meson8b_ahb_data_bus,
&meson8b_ahb_ctrl_bus,
&meson8b_hdmi_intr_sync,
&meson8b_hdmi_pclk,
&meson8b_usb1_ddr_bridge,
&meson8b_usb0_ddr_bridge,
&meson8b_mmc_pclk,
&meson8b_dvin,
&meson8b_uart2,
&meson8b_sana,
&meson8b_vpu_intr,
&meson8b_sec_ahb_ahb3_bridge,
&meson8b_clk81_a9,
&meson8b_vclk2_venci0,
&meson8b_vclk2_venci1,
&meson8b_vclk2_vencp0,
&meson8b_vclk2_vencp1,
&meson8b_gclk_venci_int,
&meson8b_gclk_vencp_int,
&meson8b_dac_clk,
&meson8b_aoclk_gate,
&meson8b_iec958_gate,
&meson8b_enc480p,
&meson8b_rng1,
&meson8b_gclk_vencl_int,
&meson8b_vclk2_venclmcc,
&meson8b_vclk2_vencl,
&meson8b_vclk2_other,
&meson8b_edp,
&meson8b_ao_media_cpu,
&meson8b_ao_ahb_sram,
&meson8b_ao_ahb_bus,
&meson8b_ao_iface,
};
static int meson8b_clkc_probe(struct platform_device *pdev)
{
void __iomem *clk_base;
@ -381,6 +609,11 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
meson8b_clk81.reg = clk_base + (u32)meson8b_clk81.reg;
/* Populate base address for gates */
for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
meson8b_clk_gates[i]->reg = clk_base +
(u32)meson8b_clk_gates[i]->reg;
/*
* register all clks
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1

151
drivers/clk/meson/meson8b.h Normal file
View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* Copyright (c) 2016 BayLibre, Inc.
* Michael Turquette <mturquette@baylibre.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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 __MESON8B_H
#define __MESON8B_H
/*
* Clock controller register offsets
*
* Register offsets from the HardKernel[0] data sheet are listed in comment
* blocks below. Those offsets must be multiplied by 4 before adding them to
* the base address to get the right value
*
* [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
*/
#define HHI_GCLK_MPEG0 0x140 /* 0x50 offset in data sheet */
#define HHI_GCLK_MPEG1 0x144 /* 0x51 offset in data sheet */
#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
#define HHI_GCLK_OTHER 0x150 /* 0x54 offset in data sheet */
#define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */
#define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */
#define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */
#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */
#define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
/*
* CLKID index values
*
* These indices are entirely contrived and do not map onto the hardware.
* Migrate them out of this header and into the DT header file when they need
* to be exposed to client nodes in DT: include/dt-bindings/clock/meson8b-clkc.h
*/
/* CLKID_UNUSED */
/* CLKID_XTAL */
/* CLKID_PLL_FIXED */
/* CLKID_PLL_VID */
/* CLKID_PLL_SYS */
/* CLKID_FCLK_DIV2 */
/* CLKID_FCLK_DIV3 */
/* CLKID_FCLK_DIV4 */
/* CLKID_FCLK_DIV5 */
/* CLKID_FCLK_DIV7 */
/* CLKID_CLK81 */
/* CLKID_MALI */
/* CLKID_CPUCLK */
/* CLKID_ZERO */
/* CLKID_MPEG_SEL */
/* CLKID_MPEG_DIV */
#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_I2S_SPDIF 35
#define CLKID_ETH 36
#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_A9 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_INT 77
#define CLKID_GCLK_VENCP_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_VENCL_INT 84
#define CLKID_VCLK2_VENCLMCC 85
#define CLKID_VCLK2_VENCL 86
#define CLKID_VCLK2_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 CLK_NR_CLKS 93
/* include the CLKIDs that have been made part of the stable DT binding */
#include <dt-bindings/clock/meson8b-clkc.h>
#endif /* __MESON8B_H */

View file

@ -209,5 +209,6 @@ config HAVE_ARM_SMCCC
source "drivers/firmware/broadcom/Kconfig"
source "drivers/firmware/google/Kconfig"
source "drivers/firmware/efi/Kconfig"
source "drivers/firmware/meson/Kconfig"
endmenu

View file

@ -22,6 +22,7 @@ obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
obj-y += broadcom/
obj-y += meson/
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
obj-$(CONFIG_EFI) += efi/
obj-$(CONFIG_UEFI_CPER) += efi/

View file

@ -0,0 +1,9 @@
#
# Amlogic Secure Monitor driver
#
config MESON_SM
bool
default ARCH_MESON
depends on ARM64_4K_PAGES
help
Say y here to enable the Amlogic secure monitor driver

View file

@ -0,0 +1 @@
obj-$(CONFIG_MESON_SM) += meson_sm.o

View file

@ -0,0 +1,248 @@
/*
* Amlogic Secure Monitor driver
*
* Copyright (C) 2016 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define pr_fmt(fmt) "meson-sm: " fmt
#include <linux/arm-smccc.h>
#include <linux/bug.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/printk.h>
#include <linux/types.h>
#include <linux/sizes.h>
#include <linux/firmware/meson/meson_sm.h>
struct meson_sm_cmd {
unsigned int index;
u32 smc_id;
};
#define CMD(d, s) { .index = (d), .smc_id = (s), }
struct meson_sm_chip {
unsigned int shmem_size;
u32 cmd_shmem_in_base;
u32 cmd_shmem_out_base;
struct meson_sm_cmd cmd[];
};
struct meson_sm_chip gxbb_chip = {
.shmem_size = SZ_4K,
.cmd_shmem_in_base = 0x82000020,
.cmd_shmem_out_base = 0x82000021,
.cmd = {
CMD(SM_EFUSE_READ, 0x82000030),
CMD(SM_EFUSE_WRITE, 0x82000031),
CMD(SM_EFUSE_USER_MAX, 0x82000033),
{ /* sentinel */ },
},
};
struct meson_sm_firmware {
const struct meson_sm_chip *chip;
void __iomem *sm_shmem_in_base;
void __iomem *sm_shmem_out_base;
};
static struct meson_sm_firmware fw;
static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
unsigned int cmd_index)
{
const struct meson_sm_cmd *cmd = chip->cmd;
while (cmd->smc_id && cmd->index != cmd_index)
cmd++;
return cmd->smc_id;
}
static u32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 arg4)
{
struct arm_smccc_res res;
arm_smccc_smc(cmd, arg0, arg1, arg2, arg3, arg4, 0, 0, &res);
return res.a0;
}
static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
{
u32 sm_phy_base;
sm_phy_base = __meson_sm_call(cmd_shmem, 0, 0, 0, 0, 0);
if (!sm_phy_base)
return 0;
return ioremap_cache(sm_phy_base, size);
}
/**
* meson_sm_call - generic SMC32 call to the secure-monitor
*
* @cmd_index: Index of the SMC32 function ID
* @ret: Returned value
* @arg0: SMC32 Argument 0
* @arg1: SMC32 Argument 1
* @arg2: SMC32 Argument 2
* @arg3: SMC32 Argument 3
* @arg4: SMC32 Argument 4
*
* Return: 0 on success, a negative value on error
*/
int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0,
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
u32 cmd, lret;
if (!fw.chip)
return -ENOENT;
cmd = meson_sm_get_cmd(fw.chip, cmd_index);
if (!cmd)
return -EINVAL;
lret = __meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
if (ret)
*ret = lret;
return 0;
}
EXPORT_SYMBOL(meson_sm_call);
/**
* meson_sm_call_read - retrieve data from secure-monitor
*
* @buffer: Buffer to store the retrieved data
* @cmd_index: Index of the SMC32 function ID
* @arg0: SMC32 Argument 0
* @arg1: SMC32 Argument 1
* @arg2: SMC32 Argument 2
* @arg3: SMC32 Argument 3
* @arg4: SMC32 Argument 4
*
* Return: size of read data on success, a negative value on error
*/
int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
u32 size;
if (!fw.chip)
return -ENOENT;
if (!fw.chip->cmd_shmem_out_base)
return -EINVAL;
if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
return -EINVAL;
if (!size || size > fw.chip->shmem_size)
return -EINVAL;
if (buffer)
memcpy(buffer, fw.sm_shmem_out_base, size);
return size;
}
EXPORT_SYMBOL(meson_sm_call_read);
/**
* meson_sm_call_write - send data to secure-monitor
*
* @buffer: Buffer containing data to send
* @size: Size of the data to send
* @cmd_index: Index of the SMC32 function ID
* @arg0: SMC32 Argument 0
* @arg1: SMC32 Argument 1
* @arg2: SMC32 Argument 2
* @arg3: SMC32 Argument 3
* @arg4: SMC32 Argument 4
*
* Return: size of sent data on success, a negative value on error
*/
int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
u32 written;
if (!fw.chip)
return -ENOENT;
if (size > fw.chip->shmem_size)
return -EINVAL;
if (!fw.chip->cmd_shmem_in_base)
return -EINVAL;
memcpy(fw.sm_shmem_in_base, buffer, size);
if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
return -EINVAL;
if (!written)
return -EINVAL;
return written;
}
EXPORT_SYMBOL(meson_sm_call_write);
static const struct of_device_id meson_sm_ids[] = {
{ .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip },
{ /* sentinel */ },
};
int __init meson_sm_init(void)
{
const struct meson_sm_chip *chip;
const struct of_device_id *matched_np;
struct device_node *np;
np = of_find_matching_node_and_match(NULL, meson_sm_ids, &matched_np);
if (!np)
return -ENODEV;
chip = matched_np->data;
if (!chip) {
pr_err("unable to setup secure-monitor data\n");
goto out;
}
if (chip->cmd_shmem_in_base) {
fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
chip->shmem_size);
if (WARN_ON(!fw.sm_shmem_in_base))
goto out;
}
if (chip->cmd_shmem_out_base) {
fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
chip->shmem_size);
if (WARN_ON(!fw.sm_shmem_out_base))
goto out_in_base;
}
fw.chip = chip;
pr_info("secure-monitor enabled\n");
return 0;
out_in_base:
iounmap(fw.sm_shmem_in_base);
out:
return -EINVAL;
}
device_initcall(meson_sm_init);

View file

@ -24,6 +24,7 @@
#define DRIVER_NAME "meson-ir"
/* valid on all Meson platforms */
#define IR_DEC_LDR_ACTIVE 0x00
#define IR_DEC_LDR_IDLE 0x04
#define IR_DEC_LDR_REPEAT 0x08
@ -32,12 +33,21 @@
#define IR_DEC_FRAME 0x14
#define IR_DEC_STATUS 0x18
#define IR_DEC_REG1 0x1c
/* only available on Meson 8b and newer */
#define IR_DEC_REG2 0x20
#define REG0_RATE_MASK (BIT(11) - 1)
#define REG1_MODE_MASK (BIT(7) | BIT(8))
#define REG1_MODE_NEC (0 << 7)
#define REG1_MODE_GENERAL (2 << 7)
#define DECODE_MODE_NEC 0x0
#define DECODE_MODE_RAW 0x2
/* Meson 6b uses REG1 to configure the mode */
#define REG1_MODE_MASK GENMASK(8, 7)
#define REG1_MODE_SHIFT 7
/* Meson 8b / GXBB use REG2 to configure the mode */
#define REG2_MODE_MASK GENMASK(3, 0)
#define REG2_MODE_SHIFT 0
#define REG1_TIME_IV_SHIFT 16
#define REG1_TIME_IV_MASK ((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
@ -158,8 +168,15 @@ static int meson_ir_probe(struct platform_device *pdev)
/* Reset the decoder */
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, REG1_RESET);
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, 0);
/* Set general operation mode */
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, REG1_MODE_GENERAL);
/* Set general operation mode (= raw/software decoding) */
if (of_device_is_compatible(node, "amlogic,meson6-ir"))
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK,
DECODE_MODE_RAW << REG1_MODE_SHIFT);
else
meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK,
DECODE_MODE_RAW << REG2_MODE_SHIFT);
/* Set rate */
meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
/* IRQ on rising and falling edges */
@ -197,6 +214,8 @@ static int meson_ir_remove(struct platform_device *pdev)
static const struct of_device_id meson_ir_match[] = {
{ .compatible = "amlogic,meson6-ir" },
{ .compatible = "amlogic,meson8b-ir" },
{ .compatible = "amlogic,meson-gxbb-ir" },
{ },
};

View file

@ -61,13 +61,13 @@ config DWMAC_LPC18XX
config DWMAC_MESON
tristate "Amlogic Meson dwmac support"
default ARCH_MESON
depends on OF && (ARCH_MESON || COMPILE_TEST)
depends on OF && COMMON_CLK && (ARCH_MESON || COMPILE_TEST)
help
Support for Ethernet controller on Amlogic Meson SoCs.
This selects the Amlogic Meson SoC glue layer support for
the stmmac device driver. This driver is used for Meson6 and
Meson8 SoCs.
the stmmac device driver. This driver is used for Meson6,
Meson8, Meson8b and GXBB SoCs.
config DWMAC_ROCKCHIP
tristate "Rockchip dwmac support"

View file

@ -9,7 +9,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o

View file

@ -1,5 +1,5 @@
/*
* Amlogic Meson DWMAC glue layer
* Amlogic Meson6 and Meson8 DWMAC glue layer
*
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
*
@ -96,5 +96,5 @@ static struct platform_driver meson6_dwmac_driver = {
module_platform_driver(meson6_dwmac_driver);
MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
MODULE_DESCRIPTION("Amlogic Meson DWMAC glue layer");
MODULE_DESCRIPTION("Amlogic Meson6 and Meson8 DWMAC glue layer");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,324 @@
/*
* Amlogic Meson8b and GXBB DWMAC glue layer
*
* Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/ethtool.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of_net.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/stmmac.h>
#include "stmmac_platform.h"
#define PRG_ETH0 0x0
#define PRG_ETH0_RGMII_MODE BIT(0)
/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
#define PRG_ETH0_CLK_M250_SEL_SHIFT 4
#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)
#define PRG_ETH0_TXDLY_SHIFT 5
#define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)
#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT)
#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT)
#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT)
#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT)
/* divider for the result of m250_sel */
#define PRG_ETH0_CLK_M250_DIV_SHIFT 7
#define PRG_ETH0_CLK_M250_DIV_WIDTH 3
/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */
#define PRG_ETH0_CLK_M25_DIV_SHIFT 10
#define PRG_ETH0_CLK_M25_DIV_WIDTH 1
#define PRG_ETH0_INVERTED_RMII_CLK BIT(11)
#define PRG_ETH0_TX_AND_PHY_REF_CLK BIT(12)
#define MUX_CLK_NUM_PARENTS 2
struct meson8b_dwmac {
struct platform_device *pdev;
void __iomem *regs;
phy_interface_t phy_mode;
struct clk_mux m250_mux;
struct clk *m250_mux_clk;
struct clk *m250_mux_parent[MUX_CLK_NUM_PARENTS];
struct clk_divider m250_div;
struct clk *m250_div_clk;
struct clk_divider m25_div;
struct clk *m25_div_clk;
};
static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
u32 mask, u32 value)
{
u32 data;
data = readl(dwmac->regs + reg);
data &= ~mask;
data |= (value & mask);
writel(data, dwmac->regs + reg);
}
static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
{
struct clk_init_data init;
int i, ret;
struct device *dev = &dwmac->pdev->dev;
char clk_name[32];
const char *clk_div_parents[1];
const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
static struct clk_div_table clk_25m_div_table[] = {
{ .val = 0, .div = 5 },
{ .val = 1, .div = 10 },
{ /* sentinel */ },
};
/* get the mux parents from DT */
for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
char name[16];
snprintf(name, sizeof(name), "clkin%d", i);
dwmac->m250_mux_parent[i] = devm_clk_get(dev, name);
if (IS_ERR(dwmac->m250_mux_parent[i])) {
ret = PTR_ERR(dwmac->m250_mux_parent[i]);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Missing clock %s\n", name);
return ret;
}
mux_parent_names[i] =
__clk_get_name(dwmac->m250_mux_parent[i]);
}
/* create the m250_mux */
snprintf(clk_name, sizeof(clk_name), "%s#m250_sel", dev_name(dev));
init.name = clk_name;
init.ops = &clk_mux_ops;
init.flags = 0;
init.parent_names = mux_parent_names;
init.num_parents = MUX_CLK_NUM_PARENTS;
dwmac->m250_mux.reg = dwmac->regs + PRG_ETH0;
dwmac->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
dwmac->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
dwmac->m250_mux.flags = 0;
dwmac->m250_mux.table = NULL;
dwmac->m250_mux.hw.init = &init;
dwmac->m250_mux_clk = devm_clk_register(dev, &dwmac->m250_mux.hw);
if (WARN_ON(IS_ERR(dwmac->m250_mux_clk)))
return PTR_ERR(dwmac->m250_mux_clk);
/* create the m250_div */
snprintf(clk_name, sizeof(clk_name), "%s#m250_div", dev_name(dev));
init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
init.ops = &clk_divider_ops;
init.flags = CLK_SET_RATE_PARENT;
clk_div_parents[0] = __clk_get_name(dwmac->m250_mux_clk);
init.parent_names = clk_div_parents;
init.num_parents = ARRAY_SIZE(clk_div_parents);
dwmac->m250_div.reg = dwmac->regs + PRG_ETH0;
dwmac->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
dwmac->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
dwmac->m250_div.hw.init = &init;
dwmac->m250_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
dwmac->m250_div_clk = devm_clk_register(dev, &dwmac->m250_div.hw);
if (WARN_ON(IS_ERR(dwmac->m250_div_clk)))
return PTR_ERR(dwmac->m250_div_clk);
/* create the m25_div */
snprintf(clk_name, sizeof(clk_name), "%s#m25_div", dev_name(dev));
init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
init.ops = &clk_divider_ops;
init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
clk_div_parents[0] = __clk_get_name(dwmac->m250_div_clk);
init.parent_names = clk_div_parents;
init.num_parents = ARRAY_SIZE(clk_div_parents);
dwmac->m25_div.reg = dwmac->regs + PRG_ETH0;
dwmac->m25_div.shift = PRG_ETH0_CLK_M25_DIV_SHIFT;
dwmac->m25_div.width = PRG_ETH0_CLK_M25_DIV_WIDTH;
dwmac->m25_div.table = clk_25m_div_table;
dwmac->m25_div.hw.init = &init;
dwmac->m25_div.flags = CLK_DIVIDER_ALLOW_ZERO;
dwmac->m25_div_clk = devm_clk_register(dev, &dwmac->m25_div.hw);
if (WARN_ON(IS_ERR(dwmac->m25_div_clk)))
return PTR_ERR(dwmac->m25_div_clk);
return 0;
}
static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
{
int ret;
unsigned long clk_rate;
switch (dwmac->phy_mode) {
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
/* Generate a 25MHz clock for the PHY */
clk_rate = 25 * 1000 * 1000;
/* enable RGMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
PRG_ETH0_RGMII_MODE);
/* only relevant for RMII mode -> disable in RGMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_INVERTED_RMII_CLK, 0);
/* TX clock delay - all known boards use a 1/4 cycle delay */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
PRG_ETH0_TXDLY_QUARTER);
break;
case PHY_INTERFACE_MODE_RMII:
/* Use the rate of the mux clock for the internal RMII PHY */
clk_rate = clk_get_rate(dwmac->m250_mux_clk);
/* disable RGMII mode -> enables RMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
0);
/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_INVERTED_RMII_CLK,
PRG_ETH0_INVERTED_RMII_CLK);
/* TX clock delay cannot be configured in RMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
0);
break;
default:
dev_err(&dwmac->pdev->dev, "unsupported phy-mode %s\n",
phy_modes(dwmac->phy_mode));
return -EINVAL;
}
ret = clk_prepare_enable(dwmac->m25_div_clk);
if (ret) {
dev_err(&dwmac->pdev->dev, "failed to enable the PHY clock\n");
return ret;
}
ret = clk_set_rate(dwmac->m25_div_clk, clk_rate);
if (ret) {
clk_disable_unprepare(dwmac->m25_div_clk);
dev_err(&dwmac->pdev->dev, "failed to set PHY clock\n");
return ret;
}
/* enable TX_CLK and PHY_REF_CLK generator */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
PRG_ETH0_TX_AND_PHY_REF_CLK);
return 0;
}
static int meson8b_dwmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
struct resource *res;
struct meson8b_dwmac *dwmac;
int ret;
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat);
dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dwmac->regs))
return PTR_ERR(dwmac->regs);
dwmac->pdev = pdev;
dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
if (dwmac->phy_mode < 0) {
dev_err(&pdev->dev, "missing phy-mode property\n");
return -EINVAL;
}
ret = meson8b_init_clk(dwmac);
if (ret)
return ret;
ret = meson8b_init_prg_eth(dwmac);
if (ret)
return ret;
plat_dat->bsp_priv = dwmac;
return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
static int meson8b_dwmac_remove(struct platform_device *pdev)
{
struct meson8b_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
clk_disable_unprepare(dwmac->m25_div_clk);
return stmmac_pltfr_remove(pdev);
}
static const struct of_device_id meson8b_dwmac_match[] = {
{ .compatible = "amlogic,meson8b-dwmac" },
{ .compatible = "amlogic,meson-gxbb-dwmac" },
{ }
};
MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
static struct platform_driver meson8b_dwmac_driver = {
.probe = meson8b_dwmac_probe,
.remove = meson8b_dwmac_remove,
.driver = {
.name = "meson8b-dwmac",
.pm = &stmmac_pltfr_pm_ops,
.of_match_table = meson8b_dwmac_match,
},
};
module_platform_driver(meson8b_dwmac_driver);
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
MODULE_DESCRIPTION("Amlogic Meson8b and GXBB DWMAC glue layer");
MODULE_LICENSE("GPL v2");

View file

@ -30,4 +30,12 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
int stmmac_pltfr_remove(struct platform_device *pdev);
extern const struct dev_pm_ops stmmac_pltfr_pm_ops;
static inline void *get_stmmac_bsp_priv(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
return priv->plat->bsp_priv;
}
#endif /* __STMMAC_PLATFORM_H__ */

View file

@ -101,4 +101,14 @@ config NVMEM_VF610_OCOTP
This driver can also be build as a module. If so, the module will
be called nvmem-vf610-ocotp.
config MESON_EFUSE
tristate "Amlogic eFuse Support"
depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
help
This is a driver to retrieve specific values from the eFuse found on
the Amlogic Meson SoCs.
This driver can also be built as a module. If so, the module
will be called nvmem_meson_efuse.
endif

View file

@ -22,3 +22,5 @@ obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
nvmem_sunxi_sid-y := sunxi_sid.o
obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
nvmem-vf610-ocotp-y := vf610-ocotp.o
obj-$(CONFIG_MESON_EFUSE) += nvmem_meson_efuse.o
nvmem_meson_efuse-y := meson-efuse.o

View file

@ -0,0 +1,93 @@
/*
* Amlogic eFuse Driver
*
* Copyright (c) 2016 Endless Computers, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License 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.
*/
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/firmware/meson/meson_sm.h>
static int meson_efuse_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
u8 *buf = val;
int ret;
ret = meson_sm_call_read(buf, SM_EFUSE_READ, offset,
bytes, 0, 0, 0);
if (ret < 0)
return ret;
return 0;
}
static struct nvmem_config econfig = {
.name = "meson-efuse",
.owner = THIS_MODULE,
.stride = 1,
.word_size = 1,
.read_only = true,
};
static const struct of_device_id meson_efuse_match[] = {
{ .compatible = "amlogic,meson-gxbb-efuse", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, meson_efuse_match);
static int meson_efuse_probe(struct platform_device *pdev)
{
struct nvmem_device *nvmem;
unsigned int size;
if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0)
return -EINVAL;
econfig.dev = &pdev->dev;
econfig.reg_read = meson_efuse_read;
econfig.size = size;
nvmem = nvmem_register(&econfig);
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
platform_set_drvdata(pdev, nvmem);
return 0;
}
static int meson_efuse_remove(struct platform_device *pdev)
{
struct nvmem_device *nvmem = platform_get_drvdata(pdev);
return nvmem_unregister(nvmem);
}
static struct platform_driver meson_efuse_driver = {
.probe = meson_efuse_probe,
.remove = meson_efuse_remove,
.driver = {
.name = "meson-efuse",
.of_match_table = meson_efuse_match,
},
};
module_platform_driver(meson_efuse_driver);
MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>");
MODULE_DESCRIPTION("Amlogic Meson NVMEM driver");
MODULE_LICENSE("GPL v2");

View file

@ -181,6 +181,38 @@ static const struct dwc2_core_params params_ltq = {
.hibernation = -1,
};
static const struct dwc2_core_params params_amlogic = {
.otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE,
.otg_ver = -1,
.dma_enable = 1,
.dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = DWC2_SPEED_PARAM_HIGH,
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = -1,
.host_rx_fifo_size = 512,
.host_nperio_tx_fifo_size = 500,
.host_perio_tx_fifo_size = 500,
.max_transfer_size = -1,
.max_packet_count = -1,
.host_channels = 16,
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
.phy_utmi_width = -1,
.phy_ulpi_ddr = -1,
.phy_ulpi_ext_vbus = -1,
.i2c_enable = -1,
.ulpi_fs_ls = -1,
.host_support_fs_ls_low_power = -1,
.host_ls_low_power_phy_clk = -1,
.ts_dline = -1,
.reload_ctl = 1,
.ahbcfg = GAHBCFG_HBSTLEN_INCR8 <<
GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = 0,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
/*
* Check the dr_mode against the module configuration and hardware
* capabilities.
@ -464,6 +496,8 @@ static const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "lantiq,xrx200-usb", .data = &params_ltq },
{ .compatible = "snps,dwc2", .data = NULL },
{ .compatible = "samsung,s3c6400-hsotg", .data = NULL},
{ .compatible = "amlogic,meson8b-usb", .data = &params_amlogic },
{ .compatible = "amlogic,meson-gxbb-usb", .data = &params_amlogic },
{},
};
MODULE_DEVICE_TABLE(of, dwc2_of_match_table);

View file

@ -6,7 +6,23 @@
#define __GXBB_CLKC_H
#define CLKID_CPUCLK 1
#define CLKID_HDMI_PLL 2
#define CLKID_FCLK_DIV2 4
#define CLKID_FCLK_DIV3 5
#define CLKID_FCLK_DIV4 6
#define CLKID_CLK81 12
#define CLKID_MPLL2 15
#define CLKID_SPI 34
#define CLKID_I2C 22
#define CLKID_ETH 36
#define CLKID_USB0 50
#define CLKID_USB1 51
#define CLKID_USB 55
#define CLKID_USB1_DDR_BRIDGE 64
#define CLKID_USB0_DDR_BRIDGE 65
#define CLKID_AO_I2C 93
#define CLKID_SD_EMMC_A 94
#define CLKID_SD_EMMC_B 95
#define CLKID_SD_EMMC_C 96
#endif /* __GXBB_CLKC_H */

View file

@ -22,6 +22,4 @@
#define CLKID_MPEG_SEL 14
#define CLKID_MPEG_DIV 15
#define CLK_NR_CLKS (CLKID_MPEG_DIV + 1)
#endif /* __MESON8B_CLKC_H */

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2016 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* 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.
*
* 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 _MESON_SM_FW_H_
#define _MESON_SM_FW_H_
enum {
SM_EFUSE_READ,
SM_EFUSE_WRITE,
SM_EFUSE_USER_MAX,
};
struct meson_sm_firmware;
int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1,
u32 arg2, u32 arg3, u32 arg4);
int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index,
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, u32 arg1,
u32 arg2, u32 arg3, u32 arg4);
#endif /* _MESON_SM_FW_H_ */