2018-07-13 15:41:06 +02:00
// SPDX-License-Identifier: GPL-2.0+
2018-11-04 11:49:32 +01:00
/*
* BRIEF MODULE DESCRIPTION
2018-03-15 07:22:35 +11:00
* PCI init for Ralink RT2880 solution
*
2018-11-04 11:49:32 +01:00
* Copyright 2007 Ralink Inc . ( bruce_chang @ ralinktech . com . tw )
2018-03-15 07:22:35 +11: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 10:27:02 +02:00
# include <linux/bitops.h>
2021-05-05 14:17:27 +02:00
# include <linux/clk.h>
2018-03-15 07:22:35 +11:00
# include <linux/delay.h>
2019-06-19 09:44:56 +02:00
# include <linux/gpio/consumer.h>
2018-08-03 10:27:02 +02:00
# include <linux/module.h>
2018-03-15 07:22:35 +11:00
# include <linux/of.h>
2018-08-03 10:26:54 +02:00
# include <linux/of_address.h>
2018-08-03 10:27:02 +02:00
# include <linux/of_pci.h>
# include <linux/of_platform.h>
# include <linux/pci.h>
2019-01-04 08:08:22 +01:00
# include <linux/phy/phy.h>
2018-03-15 07:22:35 +11:00
# include <linux/platform_device.h>
2018-08-03 10:27:02 +02:00
# include <linux/reset.h>
2019-10-06 20:10:32 +02:00
# include <linux/sys_soc.h>
2018-08-03 10:26:54 +02:00
2021-09-22 07:00:34 +02:00
/* MediaTek-specific configuration registers */
2018-11-04 11:49:51 +01:00
# define PCIE_FTS_NUM 0x70c
# define PCIE_FTS_NUM_MASK GENMASK(15, 8)
2019-06-26 14:43:18 +02:00
# define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8)
2018-11-04 11:49:51 +01:00
2018-11-04 11:49:48 +01:00
/* Host-PCI bridge registers */
2018-08-03 10:27:03 +02:00
# define RALINK_PCI_PCICFG_ADDR 0x0000
2021-09-22 07:00:34 +02:00
# define RALINK_PCI_PCIMSK_ADDR 0x000c
2018-11-04 11:49:48 +01:00
# define RALINK_PCI_CONFIG_ADDR 0x0020
# define RALINK_PCI_CONFIG_DATA 0x0024
# define RALINK_PCI_MEMBASE 0x0028
2021-09-22 07:00:34 +02:00
# define RALINK_PCI_IOBASE 0x002c
2018-05-04 14:58:36 +10:00
2018-11-04 11:49:48 +01:00
/* PCIe RC control registers */
2018-08-03 10:27:01 +02:00
# define RALINK_PCI_ID 0x0030
# define RALINK_PCI_CLASS 0x0034
# define RALINK_PCI_SUBID 0x0038
# define RALINK_PCI_STATUS 0x0050
2018-05-04 14:58:36 +10:00
2018-11-04 11:49:48 +01:00
/* Some definition values */
2018-11-04 11:49:52 +01: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 11:49:54 +01:00
# define PCIE_PORT_LINKUP BIT(0)
2021-08-23 19:08:03 +02:00
# define PCIE_PORT_CNT 3
2018-11-04 11:49:52 +01:00
2020-03-13 21:09:09 +01:00
# define PERST_DELAY_MS 100
2018-11-04 11:49:36 +01:00
2018-08-03 10:26:54 +02:00
/**
* struct mt7621_pcie_port - PCIe port information
2018-11-04 11:49:27 +01:00
* @ base : I / O mapped register base
2018-08-03 10:26:54 +02:00
* @ list : port list
* @ pcie : pointer to PCIe host info
2021-05-05 14:17:27 +02:00
* @ clk : pointer to the port clock gate
2019-01-04 08:08:22 +01:00
* @ phy : pointer to PHY control block
2018-11-04 11:49:27 +01:00
* @ pcie_rst : pointer to port reset control
2020-03-13 21:09:08 +01:00
* @ gpio_rst : gpio reset
2018-11-04 11:49:27 +01:00
* @ slot : port slot
2018-11-04 11:49:44 +01:00
* @ enabled : indicates if port is enabled
2018-08-03 10:26:54 +02:00
*/
struct mt7621_pcie_port {
void __iomem * base ;
struct list_head list ;
struct mt7621_pcie * pcie ;
2021-05-05 14:17:27 +02:00
struct clk * clk ;
2019-01-04 08:08:22 +01:00
struct phy * phy ;
2018-11-04 11:49:27 +01:00
struct reset_control * pcie_rst ;
2020-03-13 21:09:08 +01:00
struct gpio_desc * gpio_rst ;
2018-11-04 11:49:27 +01:00
u32 slot ;
2018-11-04 11:49:44 +01:00
bool enabled ;
2018-08-03 10:26:54 +02: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 20:10:32 +02:00
* @ resets_inverted : depends on chip revision
* reset lines are inverted .
2018-08-03 10:26:54 +02:00
*/
struct mt7621_pcie {
void __iomem * base ;
struct device * dev ;
struct list_head ports ;
2019-10-06 20:10:32 +02:00
bool resets_inverted ;
2018-08-03 10:26:54 +02:00
} ;
2018-08-03 10:26:56 +02:00
static inline u32 pcie_read ( struct mt7621_pcie * pcie , u32 reg )
{
2021-06-07 14:01:50 +02:00
return readl_relaxed ( pcie - > base + reg ) ;
2018-08-03 10:26:56 +02:00
}
static inline void pcie_write ( struct mt7621_pcie * pcie , u32 val , u32 reg )
{
2021-06-07 14:01:50 +02:00
writel_relaxed ( val , pcie - > base + reg ) ;
2018-08-03 10:26:56 +02:00
}
2020-03-08 10:19:27 +01:00
static inline void pcie_rmw ( struct mt7621_pcie * pcie , u32 reg , u32 clr , u32 set )
{
2021-06-07 14:01:50 +02:00
u32 val = readl_relaxed ( pcie - > base + reg ) ;
2020-03-08 10:19:27 +01:00
val & = ~ clr ;
val | = set ;
2021-06-07 14:01:50 +02:00
writel_relaxed ( val , pcie - > base + reg ) ;
2020-03-08 10:19:27 +01:00
}
2018-11-04 11:49:29 +01:00
static inline u32 pcie_port_read ( struct mt7621_pcie_port * port , u32 reg )
{
2021-06-07 14:01:50 +02:00
return readl_relaxed ( port - > base + reg ) ;
2018-11-04 11:49:29 +01:00
}
static inline void pcie_port_write ( struct mt7621_pcie_port * port ,
u32 val , u32 reg )
{
2021-06-07 14:01:50 +02:00
writel_relaxed ( val , port - > base + reg ) ;
2018-11-04 11:49:29 +01:00
}
2018-07-09 22:21:04 +02:00
static inline u32 mt7621_pci_get_cfgaddr ( unsigned int bus , unsigned int slot ,
unsigned int func , unsigned int where )
{
2021-09-22 07:00:34 +02:00
return ( ( ( where & 0xf00 ) > > 8 ) < < 24 ) | ( bus < < 16 ) | ( slot < < 11 ) |
2018-07-09 22:21:04 +02:00
( func < < 8 ) | ( where & 0xfc ) | 0x80000000 ;
}
2018-08-03 10:26:54 +02:00
static void __iomem * mt7621_pcie_map_bus ( struct pci_bus * bus ,
unsigned int devfn , int where )
{
struct mt7621_pcie * pcie = bus - > sysdata ;
u32 address = mt7621_pci_get_cfgaddr ( bus - > number , PCI_SLOT ( devfn ) ,
PCI_FUNC ( devfn ) , where ) ;
2021-06-07 14:01:50 +02:00
writel_relaxed ( address , pcie - > base + RALINK_PCI_CONFIG_ADDR ) ;
2018-08-03 10:26:54 +02:00
2018-08-03 10:27:06 +02:00
return pcie - > base + RALINK_PCI_CONFIG_DATA + ( where & 3 ) ;
2018-08-03 10:26:54 +02:00
}
2018-03-15 07:22:35 +11:00
2021-11-17 16:29:52 +01:00
static struct pci_ops mt7621_pci_ops = {
2018-08-03 10:26:54 +02:00
. map_bus = mt7621_pcie_map_bus ,
. read = pci_generic_config_read ,
. write = pci_generic_config_write ,
2018-03-15 07:22:35 +11:00
} ;
2018-11-04 11:49:50 +01:00
static u32 read_config ( struct mt7621_pcie * pcie , unsigned int dev , u32 reg )
2018-03-15 07:22:35 +11:00
{
2018-08-03 10:26:58 +02:00
u32 address = mt7621_pci_get_cfgaddr ( 0 , dev , 0 , reg ) ;
2018-08-03 10:26:57 +02:00
pcie_write ( pcie , address , RALINK_PCI_CONFIG_ADDR ) ;
2018-08-03 10:27:06 +02:00
return pcie_read ( pcie , RALINK_PCI_CONFIG_DATA ) ;
2018-03-15 07:22:35 +11:00
}
2018-11-04 11:49:50 +01:00
static void write_config ( struct mt7621_pcie * pcie , unsigned int dev ,
u32 reg , u32 val )
2018-03-15 07:22:35 +11:00
{
2018-08-03 10:26:59 +02:00
u32 address = mt7621_pci_get_cfgaddr ( 0 , dev , 0 , reg ) ;
2018-08-03 10:26:57 +02:00
pcie_write ( pcie , address , RALINK_PCI_CONFIG_ADDR ) ;
2018-08-03 10:27:06 +02:00
pcie_write ( pcie , val , RALINK_PCI_CONFIG_DATA ) ;
2018-03-15 07:22:35 +11:00
}
2020-03-13 21:09:08 +01:00
static inline void mt7621_rst_gpio_pcie_assert ( struct mt7621_pcie_port * port )
2019-06-19 09:44:56 +02:00
{
2020-03-13 21:09:08 +01:00
if ( port - > gpio_rst )
gpiod_set_value ( port - > gpio_rst , 1 ) ;
2019-06-19 09:44:56 +02:00
}
2020-03-13 21:09:08 +01:00
static inline void mt7621_rst_gpio_pcie_deassert ( struct mt7621_pcie_port * port )
2019-06-19 09:44:56 +02:00
{
2020-03-13 21:09:08 +01:00
if ( port - > gpio_rst )
gpiod_set_value ( port - > gpio_rst , 0 ) ;
2019-06-19 09:44:56 +02: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 18:54:54 +01:00
static inline void mt7621_control_assert ( struct mt7621_pcie_port * port )
{
2019-10-06 20:10:32 +02:00
struct mt7621_pcie * pcie = port - > pcie ;
2018-11-24 18:54:54 +01:00
2019-10-06 20:10:32 +02:00
if ( pcie - > resets_inverted )
2018-11-24 18:54:54 +01: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 20:10:32 +02:00
struct mt7621_pcie * pcie = port - > pcie ;
2018-11-24 18:54:54 +01:00
2019-10-06 20:10:32 +02:00
if ( pcie - > resets_inverted )
2018-11-24 18:54:54 +01:00
reset_control_deassert ( port - > pcie_rst ) ;
else
reset_control_assert ( port - > pcie_rst ) ;
}
2018-11-04 11:49:27 +01:00
static int mt7621_pcie_parse_port ( struct mt7621_pcie * pcie ,
2021-06-07 14:01:52 +02:00
struct device_node * node ,
2018-11-04 11:49:27 +01:00
int slot )
{
struct mt7621_pcie_port * port ;
struct device * dev = pcie - > dev ;
2020-04-13 07:59:42 +02:00
struct platform_device * pdev = to_platform_device ( dev ) ;
2019-01-04 08:08:22 +01:00
char name [ 10 ] ;
2021-06-07 14:01:52 +02:00
int err ;
2018-11-04 11:49:27 +01:00
port = devm_kzalloc ( dev , sizeof ( * port ) , GFP_KERNEL ) ;
if ( ! port )
return - ENOMEM ;
2020-11-23 10:36:36 +01:00
port - > base = devm_platform_ioremap_resource ( pdev , slot + 1 ) ;
2018-11-04 11:49:27 +01:00
if ( IS_ERR ( port - > base ) )
return PTR_ERR ( port - > base ) ;
2021-06-07 14:01:52 +02:00
port - > clk = devm_get_clk_from_child ( dev , node , NULL ) ;
2021-05-05 14:17:27 +02: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 14:01:52 +02:00
port - > pcie_rst = of_reset_control_get_exclusive ( node , NULL ) ;
2018-11-04 11:49:27 +01: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 08:08:22 +01:00
snprintf ( name , sizeof ( name ) , " pcie-phy%d " , slot ) ;
2021-06-07 14:01:52 +02: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 08:08:22 +01:00
2020-03-13 21:09:08 +01:00
port - > gpio_rst = devm_gpiod_get_index_optional ( dev , " reset " , slot ,
GPIOD_OUT_LOW ) ;
2020-03-20 12:01:23 +01:00
if ( IS_ERR ( port - > gpio_rst ) ) {
2021-09-22 07:00:34 +02:00
dev_err ( dev , " failed to get GPIO for PCIe%d \n " , slot ) ;
2021-06-07 14:01:52 +02:00
err = PTR_ERR ( port - > gpio_rst ) ;
goto remove_reset ;
2020-03-20 12:01:23 +01:00
}
2020-03-13 21:09:08 +01:00
2018-11-04 11:49:27 +01:00
port - > slot = slot ;
port - > pcie = pcie ;
INIT_LIST_HEAD ( & port - > list ) ;
list_add_tail ( & port - > list , & pcie - > ports ) ;
return 0 ;
2021-06-07 14:01:52 +02:00
remove_reset :
reset_control_put ( port - > pcie_rst ) ;
return err ;
2018-11-04 11:49:27 +01:00
}
2018-08-03 10:26:54 +02:00
static int mt7621_pcie_parse_dt ( struct mt7621_pcie * pcie )
{
struct device * dev = pcie - > dev ;
2020-11-23 10:36:36 +01:00
struct platform_device * pdev = to_platform_device ( dev ) ;
2018-11-04 11:49:27 +01:00
struct device_node * node = dev - > of_node , * child ;
2018-08-03 10:26:54 +02:00
int err ;
2020-11-23 10:36:36 +01:00
pcie - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2018-08-03 10:26:54 +02:00
if ( IS_ERR ( pcie - > base ) )
return PTR_ERR ( pcie - > base ) ;
2018-11-04 11:49:27 +01:00
for_each_available_child_of_node ( node , child ) {
int slot ;
err = of_pci_get_devfn ( child ) ;
if ( err < 0 ) {
2019-07-16 11:29:44 +05:30
of_node_put ( child ) ;
2018-11-04 11:49:27 +01:00
dev_err ( dev , " failed to parse devfn: %d \n " , err ) ;
return err ;
}
slot = PCI_SLOT ( err ) ;
2021-06-07 14:01:52 +02:00
err = mt7621_pcie_parse_port ( pcie , child , slot ) ;
2019-07-16 11:29:44 +05:30
if ( err ) {
of_node_put ( child ) ;
2018-11-04 11:49:27 +01:00
return err ;
2019-07-16 11:29:44 +05:30
}
2018-11-04 11:49:27 +01:00
}
2018-08-03 10:26:54 +02:00
return 0 ;
}
2018-11-04 11:49:39 +01:00
static int mt7621_pcie_init_port ( struct mt7621_pcie_port * port )
2018-11-04 11:49:30 +01:00
{
struct mt7621_pcie * pcie = port - > pcie ;
struct device * dev = pcie - > dev ;
u32 slot = port - > slot ;
2019-01-04 08:08:22 +01:00
int err ;
2018-11-04 11:49:30 +01:00
2019-01-04 08:08:22 +01:00
err = phy_init ( port - > phy ) ;
if ( err ) {
dev_err ( dev , " failed to initialize port%d phy \n " , slot ) ;
2019-06-19 09:44:56 +02:00
return err ;
2019-01-04 08:08:22 +01:00
}
err = phy_power_on ( port - > phy ) ;
if ( err ) {
dev_err ( dev , " failed to power on port%d phy \n " , slot ) ;
2019-06-21 08:15:15 +02:00
phy_exit ( port - > phy ) ;
2019-06-19 09:44:56 +02:00
return err ;
2018-11-04 11:49:30 +01:00
}
2019-01-04 08:08:22 +01:00
port - > enabled = true ;
2018-11-04 11:49:37 +01:00
2018-11-04 11:49:30 +01:00
return 0 ;
}
2020-03-13 21:09:08 +01: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 14:17:31 +02:00
msleep ( PERST_DELAY_MS ) ;
2020-03-13 21:09:08 +01: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 14:17:31 +02:00
msleep ( PERST_DELAY_MS ) ;
2020-03-13 21:09:08 +01:00
}
2021-08-23 19:08:03 +02:00
static int mt7621_pcie_init_ports ( struct mt7621_pcie * pcie )
2018-11-04 11:49:46 +01:00
{
struct device * dev = pcie - > dev ;
struct mt7621_pcie_port * port , * tmp ;
2021-08-23 19:08:03 +02:00
u8 num_disabled = 0 ;
2018-11-04 11:49:46 +01:00
int err ;
2020-03-13 21:09:08 +01:00
mt7621_pcie_reset_assert ( pcie ) ;
mt7621_pcie_reset_rc_deassert ( pcie ) ;
2019-06-19 09:44:56 +02:00
2018-11-04 11:49:46 +01:00
list_for_each_entry_safe ( port , tmp , & pcie - > ports , list ) {
u32 slot = port - > slot ;
2020-03-20 12:01:21 +01:00
if ( slot = = 1 ) {
port - > enabled = true ;
continue ;
}
2018-11-04 11:49:46 +01:00
err = mt7621_pcie_init_port ( port ) ;
if ( err ) {
2021-09-22 07:00:34 +02:00
dev_err ( dev , " initializing port %d failed \n " , slot ) ;
2018-11-04 11:49:46 +01:00
list_del ( & port - > list ) ;
}
}
2018-11-04 11:49:58 +01:00
2020-03-13 21:09:08 +01:00
mt7621_pcie_reset_ep_deassert ( pcie ) ;
2019-06-19 09:44:56 +02:00
2020-04-09 13:16:52 +02:00
tmp = NULL ;
2019-06-19 09:44:56 +02: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 19:08:03 +02:00
num_disabled + + ;
2020-04-09 13:16:52 +02:00
if ( slot = = 0 ) {
tmp = port ;
continue ;
}
if ( slot = = 1 & & tmp & & ! tmp - > enabled )
phy_power_off ( tmp - > phy ) ;
2019-06-19 09:44:56 +02:00
}
}
2021-08-23 19:08:03 +02:00
return ( num_disabled ! = PCIE_PORT_CNT ) ? 0 : - ENODEV ;
2018-11-04 11:49:46 +01:00
}
2019-06-19 09:44:56 +02:00
static void mt7621_pcie_enable_port ( struct mt7621_pcie_port * port )
2018-11-04 11:49:57 +01: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 14:01:53 +02:00
pcie_port_write ( port , PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE ,
PCI_BASE_ADDRESS_0 ) ;
2018-11-04 11:49:57 +01:00
/* configure class code and revision ID */
2021-06-07 14:01:53 +02:00
pcie_port_write ( port , PCIE_CLASS_CODE | PCIE_REVISION_ID ,
RALINK_PCI_CLASS ) ;
2021-06-07 14:01:48 +02: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 11:49:57 +01:00
}
2021-06-14 12:06:16 +02:00
static int mt7621_pcie_enable_ports ( struct pci_host_bridge * host )
2018-11-04 11:49:44 +01:00
{
2021-06-14 12:06:16 +02:00
struct mt7621_pcie * pcie = pci_host_bridge_priv ( host ) ;
2018-11-04 11:49:44 +01:00
struct device * dev = pcie - > dev ;
struct mt7621_pcie_port * port ;
2021-06-14 12:06:16 +02:00
struct resource_entry * entry ;
2021-05-05 14:17:27 +02:00
int err ;
2018-11-04 11:49:44 +01:00
2021-06-14 12:06:16 +02:00
entry = resource_list_first_type ( & host - > windows , IORESOURCE_IO ) ;
if ( ! entry ) {
2021-09-22 07:00:34 +02:00
dev_err ( dev , " cannot get io resource \n " ) ;
2021-06-14 12:06:16 +02:00
return - EINVAL ;
}
2020-03-18 10:44:45 +01:00
/* Setup MEMWIN and IOWIN */
pcie_write ( pcie , 0xffffffff , RALINK_PCI_MEMBASE ) ;
2021-09-25 22:32:24 +02:00
pcie_write ( pcie , entry - > res - > start - entry - > offset , RALINK_PCI_IOBASE ) ;
2020-03-18 10:44:45 +01:00
2018-11-04 11:49:44 +01:00
list_for_each_entry ( port , & pcie - > ports , list ) {
if ( port - > enabled ) {
2021-05-05 14:17:27 +02:00
err = clk_prepare_enable ( port - > clk ) ;
if ( err ) {
2021-06-07 14:01:48 +02:00
dev_err ( dev , " enabling clk pcie%d \n " ,
port - > slot ) ;
2021-05-05 14:17:27 +02:00
return err ;
}
2019-06-19 09:44:56 +02:00
mt7621_pcie_enable_port ( port ) ;
2020-03-20 12:01:22 +01:00
dev_info ( dev , " PCIE%d enabled \n " , port - > slot ) ;
2018-11-04 11:49:44 +01:00
}
}
2021-05-05 14:17:27 +02:00
return 0 ;
2018-11-04 11:49:44 +01:00
}
2020-11-23 10:36:35 +01:00
static int mt7621_pcie_register_host ( struct pci_host_bridge * host )
2018-08-03 10:26:54 +02:00
{
struct mt7621_pcie * pcie = pci_host_bridge_priv ( host ) ;
host - > ops = & mt7621_pci_ops ;
host - > sysdata = pcie ;
return pci_host_probe ( host ) ;
}
2019-10-06 20:10:32 +02:00
static const struct soc_device_attribute mt7621_pci_quirks_match [ ] = {
{ . soc_id = " mt7621 " , . revision = " E2 " }
} ;
2018-03-15 07:22:35 +11:00
static int mt7621_pci_probe ( struct platform_device * pdev )
{
2018-08-03 10:26:54 +02:00
struct device * dev = & pdev - > dev ;
2019-10-06 20:10:32 +02:00
const struct soc_device_attribute * attr ;
2021-06-07 14:01:52 +02:00
struct mt7621_pcie_port * port ;
2018-08-03 10:26:54 +02: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 11:49:28 +01:00
return - ENOMEM ;
2018-03-15 07:22:35 +11:00
2018-08-03 10:26:54 +02:00
pcie = pci_host_bridge_priv ( bridge ) ;
pcie - > dev = dev ;
platform_set_drvdata ( pdev , pcie ) ;
INIT_LIST_HEAD ( & pcie - > ports ) ;
2019-10-06 20:10:32 +02:00
attr = soc_device_match ( mt7621_pci_quirks_match ) ;
if ( attr )
pcie - > resets_inverted = true ;
2018-08-03 10:26:54 +02:00
err = mt7621_pcie_parse_dt ( pcie ) ;
if ( err ) {
2021-09-22 07:00:34 +02:00
dev_err ( dev , " parsing DT failed \n " ) ;
2018-08-03 10:26:54 +02:00
return err ;
}
2021-08-23 19:08:03 +02:00
err = mt7621_pcie_init_ports ( pcie ) ;
if ( err ) {
2021-09-22 07:00:34 +02:00
dev_err ( dev , " nothing connected in virtual bridges \n " ) ;
2021-08-23 19:08:03 +02:00
return 0 ;
}
2018-03-15 07:22:35 +11:00
2021-06-14 12:06:16 +02:00
err = mt7621_pcie_enable_ports ( bridge ) ;
2021-05-05 14:17:27 +02:00
if ( err ) {
2021-09-22 07:00:34 +02:00
dev_err ( dev , " error enabling pcie ports \n " ) ;
2021-06-07 14:01:52 +02:00
goto remove_resets ;
2021-05-05 14:17:27 +02:00
}
2018-03-15 07:22:35 +11:00
2021-05-05 14:17:32 +02:00
return mt7621_pcie_register_host ( bridge ) ;
2021-06-07 14:01:52 +02:00
remove_resets :
list_for_each_entry ( port , & pcie - > ports , list )
reset_control_put ( port - > pcie_rst ) ;
return err ;
}
static int mt7621_pci_remove ( struct platform_device * pdev )
{
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-15 07:22:35 +11:00
}
static const struct of_device_id mt7621_pci_ids [ ] = {
{ . compatible = " mediatek,mt7621-pci " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , mt7621_pci_ids ) ;
static struct platform_driver mt7621_pci_driver = {
. probe = mt7621_pci_probe ,
2021-06-07 14:01:52 +02:00
. remove = mt7621_pci_remove ,
2018-03-15 07:22:35 +11:00
. driver = {
. name = " mt7621-pci " ,
. of_match_table = of_match_ptr ( mt7621_pci_ids ) ,
} ,
} ;
2020-03-21 14:36:21 +01:00
builtin_platform_driver ( mt7621_pci_driver ) ;