2018-07-13 16:41:06 +03:00
// SPDX-License-Identifier: GPL-2.0+
2018-11-04 13:49:32 +03:00
/*
* BRIEF MODULE DESCRIPTION
2018-03-14 23:22:35 +03:00
* PCI init for Ralink RT2880 solution
*
2018-11-04 13:49:32 +03:00
* Copyright 2007 Ralink Inc . ( bruce_chang @ ralinktech . com . tw )
2018-03-14 23:22:35 +03:00
*
* May 2007 Bruce Chang
* Initial Release
*
* May 2009 Bruce Chang
* support RT2880 / RT3883 PCIe
*
* May 2011 Bruce Chang
* support RT6855 / MT7620 PCIe
*/
2018-08-03 11:27:02 +03:00
# include <linux/bitops.h>
2021-05-05 15:17:27 +03:00
# include <linux/clk.h>
2018-03-14 23:22:35 +03:00
# include <linux/delay.h>
2019-06-19 10:44:56 +03:00
# include <linux/gpio/consumer.h>
2018-08-03 11:27:02 +03:00
# include <linux/module.h>
2018-03-14 23:22:35 +03:00
# include <linux/of.h>
2018-08-03 11:26:54 +03:00
# include <linux/of_address.h>
2018-08-03 11:27:02 +03:00
# include <linux/of_pci.h>
# include <linux/of_platform.h>
# include <linux/pci.h>
2019-01-04 10:08:22 +03:00
# include <linux/phy/phy.h>
2018-03-14 23:22:35 +03:00
# include <linux/platform_device.h>
2018-08-03 11:27:02 +03:00
# include <linux/reset.h>
2019-10-06 21:10:32 +03:00
# include <linux/sys_soc.h>
2018-08-03 11:26:54 +03:00
2022-09-24 12:24:04 +03:00
# include "../pci.h"
2021-09-22 08:00:34 +03:00
/* MediaTek-specific configuration registers */
2018-11-04 13:49:51 +03:00
# define PCIE_FTS_NUM 0x70c
# define PCIE_FTS_NUM_MASK GENMASK(15, 8)
2019-06-26 15:43:18 +03:00
# define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8)
2018-11-04 13:49:51 +03:00
2018-11-04 13:49:48 +03:00
/* Host-PCI bridge registers */
2018-08-03 11:27:03 +03:00
# define RALINK_PCI_PCICFG_ADDR 0x0000
2021-09-22 08:00:34 +03:00
# define RALINK_PCI_PCIMSK_ADDR 0x000c
2018-11-04 13:49:48 +03:00
# define RALINK_PCI_CONFIG_ADDR 0x0020
# define RALINK_PCI_CONFIG_DATA 0x0024
# define RALINK_PCI_MEMBASE 0x0028
2021-09-22 08:00:34 +03:00
# define RALINK_PCI_IOBASE 0x002c
2018-05-04 07:58:36 +03:00
2018-11-04 13:49:48 +03:00
/* PCIe RC control registers */
2018-08-03 11:27:01 +03:00
# define RALINK_PCI_ID 0x0030
# define RALINK_PCI_CLASS 0x0034
# define RALINK_PCI_SUBID 0x0038
# define RALINK_PCI_STATUS 0x0050
2018-05-04 07:58:36 +03:00
2018-11-04 13:49:48 +03:00
/* Some definition values */
2018-11-04 13:49:52 +03:00
# define PCIE_REVISION_ID BIT(0)
# define PCIE_CLASS_CODE (0x60400 << 8)
# define PCIE_BAR_MAP_MAX GENMASK(30, 16)
# define PCIE_BAR_ENABLE BIT(0)
# define PCIE_PORT_INT_EN(x) BIT(20 + (x))
2018-11-04 13:49:54 +03:00
# define PCIE_PORT_LINKUP BIT(0)
2021-08-23 20:08:03 +03:00
# define PCIE_PORT_CNT 3
2018-11-04 13:49:52 +03:00
2020-03-13 23:09:09 +03:00
# define PERST_DELAY_MS 100
2018-11-04 13:49:36 +03:00
2018-08-03 11:26:54 +03:00
/**
* struct mt7621_pcie_port - PCIe port information
2018-11-04 13:49:27 +03:00
* @ base : I / O mapped register base
2018-08-03 11:26:54 +03:00
* @ list : port list
* @ pcie : pointer to PCIe host info
2021-05-05 15:17:27 +03:00
* @ clk : pointer to the port clock gate
2019-01-04 10:08:22 +03:00
* @ phy : pointer to PHY control block
2018-11-04 13:49:27 +03:00
* @ pcie_rst : pointer to port reset control
2020-03-13 23:09:08 +03:00
* @ gpio_rst : gpio reset
2018-11-04 13:49:27 +03:00
* @ slot : port slot
2018-11-04 13:49:44 +03:00
* @ enabled : indicates if port is enabled
2018-08-03 11:26:54 +03:00
*/
struct mt7621_pcie_port {
void __iomem * base ;
struct list_head list ;
struct mt7621_pcie * pcie ;
2021-05-05 15:17:27 +03:00
struct clk * clk ;
2019-01-04 10:08:22 +03:00
struct phy * phy ;
2018-11-04 13:49:27 +03:00
struct reset_control * pcie_rst ;
2020-03-13 23:09:08 +03:00
struct gpio_desc * gpio_rst ;
2018-11-04 13:49:27 +03:00
u32 slot ;
2018-11-04 13:49:44 +03:00
bool enabled ;
2018-08-03 11:26:54 +03:00
} ;
/**
* struct mt7621_pcie - PCIe host information
* @ base : IO Mapped Register Base
* @ dev : Pointer to PCIe device
* @ ports : pointer to PCIe port information
2019-10-06 21:10:32 +03:00
* @ resets_inverted : depends on chip revision
* reset lines are inverted .
2018-08-03 11:26:54 +03:00
*/
struct mt7621_pcie {
struct device * dev ;
2021-12-23 04:10:48 +03:00
void __iomem * base ;
2018-08-03 11:26:54 +03:00
struct list_head ports ;
2019-10-06 21:10:32 +03:00
bool resets_inverted ;
2018-08-03 11:26:54 +03:00
} ;
2018-08-03 11:26:56 +03:00
static inline u32 pcie_read ( struct mt7621_pcie * pcie , u32 reg )
{
2021-06-07 15:01:50 +03:00
return readl_relaxed ( pcie - > base + reg ) ;
2018-08-03 11:26:56 +03:00
}
static inline void pcie_write ( struct mt7621_pcie * pcie , u32 val , u32 reg )
{
2021-06-07 15:01:50 +03:00
writel_relaxed ( val , pcie - > base + reg ) ;
2018-08-03 11:26:56 +03:00
}
2018-11-04 13:49:29 +03:00
static inline u32 pcie_port_read ( struct mt7621_pcie_port * port , u32 reg )
{
2021-06-07 15:01:50 +03:00
return readl_relaxed ( port - > base + reg ) ;
2018-11-04 13:49:29 +03:00
}
static inline void pcie_port_write ( struct mt7621_pcie_port * port ,
u32 val , u32 reg )
{
2021-06-07 15:01:50 +03:00
writel_relaxed ( val , port - > base + reg ) ;
2018-11-04 13:49:29 +03:00
}
2018-08-03 11:26:54 +03:00
static void __iomem * mt7621_pcie_map_bus ( struct pci_bus * bus ,
unsigned int devfn , int where )
{
struct mt7621_pcie * pcie = bus - > sysdata ;
2022-09-24 12:24:04 +03:00
u32 address = PCI_CONF1_EXT_ADDRESS ( bus - > number , PCI_SLOT ( devfn ) ,
PCI_FUNC ( devfn ) , where ) ;
2018-08-03 11:26:54 +03:00
2021-06-07 15:01:50 +03:00
writel_relaxed ( address , pcie - > base + RALINK_PCI_CONFIG_ADDR ) ;
2018-08-03 11:26:54 +03:00
2018-08-03 11:27:06 +03:00
return pcie - > base + RALINK_PCI_CONFIG_DATA + ( where & 3 ) ;
2018-08-03 11:26:54 +03:00
}
2018-03-14 23:22:35 +03:00
Merge branch 'pci/driver-cleanup'
- Use of_device_get_match_data(), not of_match_device(), when we only need
the device data in altera, artpec6, cadence, designware-plat, dra7xx,
keystone, kirin (Fan Fei)
- Drop pointless of_device_get_match_data() cast in j721e (Bjorn Helgaas)
- Drop redundant struct device * from j721e since struct cdns_pcie already
has one (Bjorn Helgaas)
- Rename driver structs to *_pcie in intel-gw, iproc, ls-gen4,
mediatek-gen3, microchip, mt7621, rcar-gen2, tegra194, uniphier, xgene,
xilinx, xilinx-cpm for consistency across drivers (Fan Fei)
- Fix invalid address space conversions in hisi, spear13xx (Bjorn Helgaas)
* pci/driver-cleanup:
PCI: spear13xx: Avoid invalid address space conversions
PCI: hisi: Avoid invalid address space conversions
PCI: xilinx-cpm: Rename xilinx_cpm_pcie_port to xilinx_cpm_pcie
PCI: xilinx: Rename xilinx_pcie_port to xilinx_pcie
PCI: xgene: Rename xgene_pcie_port to xgene_pcie
PCI: uniphier: Rename uniphier_pcie_priv to uniphier_pcie
PCI: tegra194: Rename tegra_pcie_dw to tegra194_pcie
PCI: rcar-gen2: Rename rcar_pci_priv to rcar_pci
PCI: mt7621: Rename mt7621_pci_ to mt7621_pcie_
PCI: microchip: Rename mc_port to mc_pcie
PCI: mediatek-gen3: Rename mtk_pcie_port to mtk_gen3_pcie
PCI: ls-gen4: Rename ls_pcie_g4 to ls_g4_pcie
PCI: iproc: Rename iproc_pcie_pltfm_ to iproc_pltfm_pcie_
PCI: iproc: Rename iproc_pcie_bcma_ to iproc_bcma_pcie_
PCI: intel-gw: Rename intel_pcie_port to intel_pcie
PCI: j721e: Drop redundant struct device *
PCI: j721e: Drop pointless of_device_get_match_data() cast
PCI: kirin: Prefer of_device_get_match_data()
PCI: keystone: Prefer of_device_get_match_data()
PCI: dra7xx: Prefer of_device_get_match_data()
PCI: designware-plat: Prefer of_device_get_match_data()
PCI: cadence: Prefer of_device_get_match_data()
PCI: artpec6: Prefer of_device_get_match_data()
PCI: altera: Prefer of_device_get_match_data()
# Conflicts:
# drivers/pci/controller/pcie-mt7621.c
2022-01-13 18:57:53 +03:00
static struct pci_ops mt7621_pcie_ops = {
2018-08-03 11:26:54 +03:00
. map_bus = mt7621_pcie_map_bus ,
. read = pci_generic_config_read ,
. write = pci_generic_config_write ,
2018-03-14 23:22:35 +03:00
} ;
2018-11-04 13:49:50 +03:00
static u32 read_config ( struct mt7621_pcie * pcie , unsigned int dev , u32 reg )
2018-03-14 23:22:35 +03:00
{
2022-09-24 12:24:04 +03:00
u32 address = PCI_CONF1_EXT_ADDRESS ( 0 , dev , 0 , reg ) ;
2018-08-03 11:26:57 +03:00
pcie_write ( pcie , address , RALINK_PCI_CONFIG_ADDR ) ;
2018-08-03 11:27:06 +03:00
return pcie_read ( pcie , RALINK_PCI_CONFIG_DATA ) ;
2018-03-14 23:22:35 +03:00
}
2018-11-04 13:49:50 +03:00
static void write_config ( struct mt7621_pcie * pcie , unsigned int dev ,
u32 reg , u32 val )
2018-03-14 23:22:35 +03:00
{
2022-09-24 12:24:04 +03:00
u32 address = PCI_CONF1_EXT_ADDRESS ( 0 , dev , 0 , reg ) ;
2018-08-03 11:26:57 +03:00
pcie_write ( pcie , address , RALINK_PCI_CONFIG_ADDR ) ;
2018-08-03 11:27:06 +03:00
pcie_write ( pcie , val , RALINK_PCI_CONFIG_DATA ) ;
2018-03-14 23:22:35 +03:00
}
2020-03-13 23:09:08 +03:00
static inline void mt7621_rst_gpio_pcie_assert ( struct mt7621_pcie_port * port )
2019-06-19 10:44:56 +03:00
{
2020-03-13 23:09:08 +03:00
if ( port - > gpio_rst )
gpiod_set_value ( port - > gpio_rst , 1 ) ;
2019-06-19 10:44:56 +03:00
}
2020-03-13 23:09:08 +03:00
static inline void mt7621_rst_gpio_pcie_deassert ( struct mt7621_pcie_port * port )
2019-06-19 10:44:56 +03:00
{
2020-03-13 23:09:08 +03:00
if ( port - > gpio_rst )
gpiod_set_value ( port - > gpio_rst , 0 ) ;
2019-06-19 10:44:56 +03:00
}
static inline bool mt7621_pcie_port_is_linkup ( struct mt7621_pcie_port * port )
{
return ( pcie_port_read ( port , RALINK_PCI_STATUS ) & PCIE_PORT_LINKUP ) ! = 0 ;
}
2018-11-24 20:54:54 +03:00
static inline void mt7621_control_assert ( struct mt7621_pcie_port * port )
{
2019-10-06 21:10:32 +03:00
struct mt7621_pcie * pcie = port - > pcie ;
2018-11-24 20:54:54 +03:00
2019-10-06 21:10:32 +03:00
if ( pcie - > resets_inverted )
2018-11-24 20:54:54 +03:00
reset_control_assert ( port - > pcie_rst ) ;
else
reset_control_deassert ( port - > pcie_rst ) ;
}
static inline void mt7621_control_deassert ( struct mt7621_pcie_port * port )
{
2019-10-06 21:10:32 +03:00
struct mt7621_pcie * pcie = port - > pcie ;
2018-11-24 20:54:54 +03:00
2019-10-06 21:10:32 +03:00
if ( pcie - > resets_inverted )
2018-11-24 20:54:54 +03:00
reset_control_deassert ( port - > pcie_rst ) ;
else
reset_control_assert ( port - > pcie_rst ) ;
}
2018-11-04 13:49:27 +03:00
static int mt7621_pcie_parse_port ( struct mt7621_pcie * pcie ,
2021-06-07 15:01:52 +03:00
struct device_node * node ,
2018-11-04 13:49:27 +03:00
int slot )
{
struct mt7621_pcie_port * port ;
struct device * dev = pcie - > dev ;
2020-04-13 08:59:42 +03:00
struct platform_device * pdev = to_platform_device ( dev ) ;
2019-01-04 10:08:22 +03:00
char name [ 10 ] ;
2021-06-07 15:01:52 +03:00
int err ;
2018-11-04 13:49:27 +03:00
port = devm_kzalloc ( dev , sizeof ( * port ) , GFP_KERNEL ) ;
if ( ! port )
return - ENOMEM ;
2020-11-23 12:36:36 +03:00
port - > base = devm_platform_ioremap_resource ( pdev , slot + 1 ) ;
2018-11-04 13:49:27 +03:00
if ( IS_ERR ( port - > base ) )
return PTR_ERR ( port - > base ) ;
2021-06-07 15:01:52 +03:00
port - > clk = devm_get_clk_from_child ( dev , node , NULL ) ;
2021-05-05 15:17:27 +03:00
if ( IS_ERR ( port - > clk ) ) {
dev_err ( dev , " failed to get pcie%d clock \n " , slot ) ;
return PTR_ERR ( port - > clk ) ;
}
2021-06-07 15:01:52 +03:00
port - > pcie_rst = of_reset_control_get_exclusive ( node , NULL ) ;
2018-11-04 13:49:27 +03:00
if ( PTR_ERR ( port - > pcie_rst ) = = - EPROBE_DEFER ) {
dev_err ( dev , " failed to get pcie%d reset control \n " , slot ) ;
return PTR_ERR ( port - > pcie_rst ) ;
}
2019-01-04 10:08:22 +03:00
snprintf ( name , sizeof ( name ) , " pcie-phy%d " , slot ) ;
2021-06-07 15:01:52 +03:00
port - > phy = devm_of_phy_get ( dev , node , name ) ;
if ( IS_ERR ( port - > phy ) ) {
dev_err ( dev , " failed to get pcie-phy%d \n " , slot ) ;
err = PTR_ERR ( port - > phy ) ;
goto remove_reset ;
}
2019-01-04 10:08:22 +03:00
2020-03-13 23:09:08 +03:00
port - > gpio_rst = devm_gpiod_get_index_optional ( dev , " reset " , slot ,
GPIOD_OUT_LOW ) ;
2020-03-20 14:01:23 +03:00
if ( IS_ERR ( port - > gpio_rst ) ) {
2021-09-22 08:00:34 +03:00
dev_err ( dev , " failed to get GPIO for PCIe%d \n " , slot ) ;
2021-06-07 15:01:52 +03:00
err = PTR_ERR ( port - > gpio_rst ) ;
goto remove_reset ;
2020-03-20 14:01:23 +03:00
}
2020-03-13 23:09:08 +03:00
2018-11-04 13:49:27 +03:00
port - > slot = slot ;
port - > pcie = pcie ;
INIT_LIST_HEAD ( & port - > list ) ;
list_add_tail ( & port - > list , & pcie - > ports ) ;
return 0 ;
2021-06-07 15:01:52 +03:00
remove_reset :
reset_control_put ( port - > pcie_rst ) ;
return err ;
2018-11-04 13:49:27 +03:00
}
2018-08-03 11:26:54 +03:00
static int mt7621_pcie_parse_dt ( struct mt7621_pcie * pcie )
{
struct device * dev = pcie - > dev ;
2020-11-23 12:36:36 +03:00
struct platform_device * pdev = to_platform_device ( dev ) ;
2018-11-04 13:49:27 +03:00
struct device_node * node = dev - > of_node , * child ;
2018-08-03 11:26:54 +03:00
int err ;
2020-11-23 12:36:36 +03:00
pcie - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2018-08-03 11:26:54 +03:00
if ( IS_ERR ( pcie - > base ) )
return PTR_ERR ( pcie - > base ) ;
2018-11-04 13:49:27 +03:00
for_each_available_child_of_node ( node , child ) {
int slot ;
err = of_pci_get_devfn ( child ) ;
if ( err < 0 ) {
2019-07-16 08:59:44 +03:00
of_node_put ( child ) ;
2018-11-04 13:49:27 +03:00
dev_err ( dev , " failed to parse devfn: %d \n " , err ) ;
return err ;
}
slot = PCI_SLOT ( err ) ;
2021-06-07 15:01:52 +03:00
err = mt7621_pcie_parse_port ( pcie , child , slot ) ;
2019-07-16 08:59:44 +03:00
if ( err ) {
of_node_put ( child ) ;
2018-11-04 13:49:27 +03:00
return err ;
2019-07-16 08:59:44 +03:00
}
2018-11-04 13:49:27 +03:00
}
2018-08-03 11:26:54 +03:00
return 0 ;
}
2018-11-04 13:49:39 +03:00
static int mt7621_pcie_init_port ( struct mt7621_pcie_port * port )
2018-11-04 13:49:30 +03:00
{
struct mt7621_pcie * pcie = port - > pcie ;
struct device * dev = pcie - > dev ;
u32 slot = port - > slot ;
2019-01-04 10:08:22 +03:00
int err ;
2018-11-04 13:49:30 +03:00
2019-01-04 10:08:22 +03:00
err = phy_init ( port - > phy ) ;
if ( err ) {
dev_err ( dev , " failed to initialize port%d phy \n " , slot ) ;
2019-06-19 10:44:56 +03:00
return err ;
2019-01-04 10:08:22 +03:00
}
err = phy_power_on ( port - > phy ) ;
if ( err ) {
dev_err ( dev , " failed to power on port%d phy \n " , slot ) ;
2019-06-21 09:15:15 +03:00
phy_exit ( port - > phy ) ;
2019-06-19 10:44:56 +03:00
return err ;
2018-11-04 13:49:30 +03:00
}
2019-01-04 10:08:22 +03:00
port - > enabled = true ;
2018-11-04 13:49:37 +03:00
2018-11-04 13:49:30 +03:00
return 0 ;
}
2020-03-13 23:09:08 +03:00
static void mt7621_pcie_reset_assert ( struct mt7621_pcie * pcie )
{
struct mt7621_pcie_port * port ;
list_for_each_entry ( port , & pcie - > ports , list ) {
/* PCIe RC reset assert */
mt7621_control_assert ( port ) ;
/* PCIe EP reset assert */
mt7621_rst_gpio_pcie_assert ( port ) ;
}
2021-05-05 15:17:31 +03:00
msleep ( PERST_DELAY_MS ) ;
2020-03-13 23:09:08 +03:00
}
static void mt7621_pcie_reset_rc_deassert ( struct mt7621_pcie * pcie )
{
struct mt7621_pcie_port * port ;
list_for_each_entry ( port , & pcie - > ports , list )
mt7621_control_deassert ( port ) ;
}
static void mt7621_pcie_reset_ep_deassert ( struct mt7621_pcie * pcie )
{
struct mt7621_pcie_port * port ;
list_for_each_entry ( port , & pcie - > ports , list )
mt7621_rst_gpio_pcie_deassert ( port ) ;
2021-05-05 15:17:31 +03:00
msleep ( PERST_DELAY_MS ) ;
2020-03-13 23:09:08 +03:00
}
2021-08-23 20:08:03 +03:00
static int mt7621_pcie_init_ports ( struct mt7621_pcie * pcie )
2018-11-04 13:49:46 +03:00
{
struct device * dev = pcie - > dev ;
struct mt7621_pcie_port * port , * tmp ;
2021-08-23 20:08:03 +03:00
u8 num_disabled = 0 ;
2018-11-04 13:49:46 +03:00
int err ;
2020-03-13 23:09:08 +03:00
mt7621_pcie_reset_assert ( pcie ) ;
mt7621_pcie_reset_rc_deassert ( pcie ) ;
2019-06-19 10:44:56 +03:00
2018-11-04 13:49:46 +03:00
list_for_each_entry_safe ( port , tmp , & pcie - > ports , list ) {
u32 slot = port - > slot ;
2020-03-20 14:01:21 +03:00
if ( slot = = 1 ) {
port - > enabled = true ;
continue ;
}
2018-11-04 13:49:46 +03:00
err = mt7621_pcie_init_port ( port ) ;
if ( err ) {
2021-09-22 08:00:34 +03:00
dev_err ( dev , " initializing port %d failed \n " , slot ) ;
2018-11-04 13:49:46 +03:00
list_del ( & port - > list ) ;
}
}
2018-11-04 13:49:58 +03:00
2020-03-13 23:09:08 +03:00
mt7621_pcie_reset_ep_deassert ( pcie ) ;
2019-06-19 10:44:56 +03:00
2020-04-09 14:16:52 +03:00
tmp = NULL ;
2019-06-19 10:44:56 +03:00
list_for_each_entry ( port , & pcie - > ports , list ) {
u32 slot = port - > slot ;
if ( ! mt7621_pcie_port_is_linkup ( port ) ) {
dev_err ( dev , " pcie%d no card, disable it (RST & CLK) \n " ,
slot ) ;
mt7621_control_assert ( port ) ;
port - > enabled = false ;
2021-08-23 20:08:03 +03:00
num_disabled + + ;
2020-04-09 14:16:52 +03:00
if ( slot = = 0 ) {
tmp = port ;
continue ;
}
if ( slot = = 1 & & tmp & & ! tmp - > enabled )
phy_power_off ( tmp - > phy ) ;
2019-06-19 10:44:56 +03:00
}
}
2021-08-23 20:08:03 +03:00
return ( num_disabled ! = PCIE_PORT_CNT ) ? 0 : - ENODEV ;
2018-11-04 13:49:46 +03:00
}
2019-06-19 10:44:56 +03:00
static void mt7621_pcie_enable_port ( struct mt7621_pcie_port * port )
2018-11-04 13:49:57 +03:00
{
struct mt7621_pcie * pcie = port - > pcie ;
u32 slot = port - > slot ;
u32 val ;
/* enable pcie interrupt */
val = pcie_read ( pcie , RALINK_PCI_PCIMSK_ADDR ) ;
val | = PCIE_PORT_INT_EN ( slot ) ;
pcie_write ( pcie , val , RALINK_PCI_PCIMSK_ADDR ) ;
/* map 2G DDR region */
2021-06-07 15:01:53 +03:00
pcie_port_write ( port , PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE ,
PCI_BASE_ADDRESS_0 ) ;
2018-11-04 13:49:57 +03:00
/* configure class code and revision ID */
2021-06-07 15:01:53 +03:00
pcie_port_write ( port , PCIE_CLASS_CODE | PCIE_REVISION_ID ,
RALINK_PCI_CLASS ) ;
2021-06-07 15:01:48 +03:00
/* configure RC FTS number to 250 when it leaves L0s */
val = read_config ( pcie , slot , PCIE_FTS_NUM ) ;
val & = ~ PCIE_FTS_NUM_MASK ;
val | = PCIE_FTS_NUM_L0 ( 0x50 ) ;
write_config ( pcie , slot , PCIE_FTS_NUM , val ) ;
2018-11-04 13:49:57 +03:00
}
2021-06-14 13:06:16 +03:00
static int mt7621_pcie_enable_ports ( struct pci_host_bridge * host )
2018-11-04 13:49:44 +03:00
{
2021-06-14 13:06:16 +03:00
struct mt7621_pcie * pcie = pci_host_bridge_priv ( host ) ;
2018-11-04 13:49:44 +03:00
struct device * dev = pcie - > dev ;
struct mt7621_pcie_port * port ;
2021-06-14 13:06:16 +03:00
struct resource_entry * entry ;
2021-05-05 15:17:27 +03:00
int err ;
2018-11-04 13:49:44 +03:00
2021-06-14 13:06:16 +03:00
entry = resource_list_first_type ( & host - > windows , IORESOURCE_IO ) ;
if ( ! entry ) {
2021-09-22 08:00:34 +03:00
dev_err ( dev , " cannot get io resource \n " ) ;
2021-06-14 13:06:16 +03:00
return - EINVAL ;
}
2020-03-18 12:44:45 +03:00
/* Setup MEMWIN and IOWIN */
pcie_write ( pcie , 0xffffffff , RALINK_PCI_MEMBASE ) ;
2021-09-25 23:32:24 +03:00
pcie_write ( pcie , entry - > res - > start - entry - > offset , RALINK_PCI_IOBASE ) ;
2020-03-18 12:44:45 +03:00
2018-11-04 13:49:44 +03:00
list_for_each_entry ( port , & pcie - > ports , list ) {
if ( port - > enabled ) {
2021-05-05 15:17:27 +03:00
err = clk_prepare_enable ( port - > clk ) ;
if ( err ) {
2021-06-07 15:01:48 +03:00
dev_err ( dev , " enabling clk pcie%d \n " ,
port - > slot ) ;
2021-05-05 15:17:27 +03:00
return err ;
}
2019-06-19 10:44:56 +03:00
mt7621_pcie_enable_port ( port ) ;
2020-03-20 14:01:22 +03:00
dev_info ( dev , " PCIE%d enabled \n " , port - > slot ) ;
2018-11-04 13:49:44 +03:00
}
}
2021-05-05 15:17:27 +03:00
return 0 ;
2018-11-04 13:49:44 +03:00
}
2020-11-23 12:36:35 +03:00
static int mt7621_pcie_register_host ( struct pci_host_bridge * host )
2018-08-03 11:26:54 +03:00
{
struct mt7621_pcie * pcie = pci_host_bridge_priv ( host ) ;
2021-12-23 04:10:48 +03:00
host - > ops = & mt7621_pcie_ops ;
2018-08-03 11:26:54 +03:00
host - > sysdata = pcie ;
return pci_host_probe ( host ) ;
}
2021-12-23 04:10:48 +03:00
static const struct soc_device_attribute mt7621_pcie_quirks_match [ ] = {
2022-12-05 23:46:45 +03:00
{ . soc_id = " mt7621 " , . revision = " E2 " } ,
{ /* sentinel */ }
2019-10-06 21:10:32 +03:00
} ;
2021-12-23 04:10:48 +03:00
static int mt7621_pcie_probe ( struct platform_device * pdev )
2018-03-14 23:22:35 +03:00
{
2018-08-03 11:26:54 +03:00
struct device * dev = & pdev - > dev ;
2019-10-06 21:10:32 +03:00
const struct soc_device_attribute * attr ;
2021-06-07 15:01:52 +03:00
struct mt7621_pcie_port * port ;
2018-08-03 11:26:54 +03:00
struct mt7621_pcie * pcie ;
struct pci_host_bridge * bridge ;
int err ;
if ( ! dev - > of_node )
return - ENODEV ;
bridge = devm_pci_alloc_host_bridge ( dev , sizeof ( * pcie ) ) ;
if ( ! bridge )
2018-11-04 13:49:28 +03:00
return - ENOMEM ;
2018-03-14 23:22:35 +03:00
2018-08-03 11:26:54 +03:00
pcie = pci_host_bridge_priv ( bridge ) ;
pcie - > dev = dev ;
platform_set_drvdata ( pdev , pcie ) ;
INIT_LIST_HEAD ( & pcie - > ports ) ;
2021-12-23 04:10:48 +03:00
attr = soc_device_match ( mt7621_pcie_quirks_match ) ;
2019-10-06 21:10:32 +03:00
if ( attr )
pcie - > resets_inverted = true ;
2018-08-03 11:26:54 +03:00
err = mt7621_pcie_parse_dt ( pcie ) ;
if ( err ) {
2021-09-22 08:00:34 +03:00
dev_err ( dev , " parsing DT failed \n " ) ;
2018-08-03 11:26:54 +03:00
return err ;
}
2021-08-23 20:08:03 +03:00
err = mt7621_pcie_init_ports ( pcie ) ;
if ( err ) {
2021-09-22 08:00:34 +03:00
dev_err ( dev , " nothing connected in virtual bridges \n " ) ;
2021-08-23 20:08:03 +03:00
return 0 ;
}
2018-03-14 23:22:35 +03:00
2021-06-14 13:06:16 +03:00
err = mt7621_pcie_enable_ports ( bridge ) ;
2021-05-05 15:17:27 +03:00
if ( err ) {
2021-09-22 08:00:34 +03:00
dev_err ( dev , " error enabling pcie ports \n " ) ;
2021-06-07 15:01:52 +03:00
goto remove_resets ;
2021-05-05 15:17:27 +03:00
}
2018-03-14 23:22:35 +03:00
2021-05-05 15:17:32 +03:00
return mt7621_pcie_register_host ( bridge ) ;
2021-06-07 15:01:52 +03:00
remove_resets :
list_for_each_entry ( port , & pcie - > ports , list )
reset_control_put ( port - > pcie_rst ) ;
return err ;
}
2021-12-23 04:10:48 +03:00
static int mt7621_pcie_remove ( struct platform_device * pdev )
2021-06-07 15:01:52 +03:00
{
struct mt7621_pcie * pcie = platform_get_drvdata ( pdev ) ;
struct mt7621_pcie_port * port ;
list_for_each_entry ( port , & pcie - > ports , list )
reset_control_put ( port - > pcie_rst ) ;
return 0 ;
2018-03-14 23:22:35 +03:00
}
2021-12-23 04:10:48 +03:00
static const struct of_device_id mt7621_pcie_ids [ ] = {
2018-03-14 23:22:35 +03:00
{ . compatible = " mediatek,mt7621-pci " } ,
{ } ,
} ;
2021-12-23 04:10:48 +03:00
MODULE_DEVICE_TABLE ( of , mt7621_pcie_ids ) ;
2018-03-14 23:22:35 +03:00
2021-12-23 04:10:48 +03:00
static struct platform_driver mt7621_pcie_driver = {
. probe = mt7621_pcie_probe ,
. remove = mt7621_pcie_remove ,
2018-03-14 23:22:35 +03:00
. driver = {
. name = " mt7621-pci " ,
2022-01-24 14:30:02 +03:00
. of_match_table = mt7621_pcie_ids ,
2018-03-14 23:22:35 +03:00
} ,
} ;
2021-12-23 04:10:48 +03:00
builtin_platform_driver ( mt7621_pcie_driver ) ;
2021-12-07 13:49:23 +03:00
MODULE_LICENSE ( " GPL v2 " ) ;