306 lines
10 KiB
C
Executable File
306 lines
10 KiB
C
Executable File
/***************************************************************
|
||
Copyright Statement:
|
||
|
||
This software/firmware and related documentation (<28><>EcoNet Software<72><65>)
|
||
are protected under relevant copyright laws. The information contained herein
|
||
is confidential and proprietary to EcoNet (HK) Limited (<28><>EcoNet<65><74>) and/or
|
||
its licensors. Without the prior written permission of EcoNet and/or its licensors,
|
||
any reproduction, modification, use or disclosure of EcoNet Software, and
|
||
information contained herein, in whole or in part, shall be strictly prohibited.
|
||
|
||
EcoNet (HK) Limited EcoNet. ALL RIGHTS RESERVED.
|
||
|
||
BY OPENING OR USING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY
|
||
ACKNOWLEDGES AND AGREES THAT THE SOFTWARE/FIRMWARE AND ITS
|
||
DOCUMENTATIONS (<28><>ECONET SOFTWARE<52><45>) RECEIVED FROM ECONET
|
||
AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON AN <20><>AS IS<49><53>
|
||
BASIS ONLY. ECONET EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
|
||
WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
||
OR NON-INFRINGEMENT. NOR DOES ECONET PROVIDE ANY WARRANTY
|
||
WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTIES WHICH
|
||
MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE ECONET SOFTWARE.
|
||
RECEIVER AGREES TO LOOK ONLY TO SUCH THIRD PARTIES FOR ANY AND ALL
|
||
WARRANTY CLAIMS RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
|
||
THAT IT IS RECEIVER<45><52>S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD
|
||
PARTY ALL PROPER LICENSES CONTAINED IN ECONET SOFTWARE.
|
||
|
||
ECONET SHALL NOT BE RESPONSIBLE FOR ANY ECONET SOFTWARE RELEASES
|
||
MADE TO RECEIVER<45><52>S SPECIFICATION OR CONFORMING TO A PARTICULAR
|
||
STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND
|
||
ECONET'S ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE ECONET
|
||
SOFTWARE RELEASED HEREUNDER SHALL BE, AT ECONET'S SOLE OPTION, TO
|
||
REVISE OR REPLACE THE ECONET SOFTWARE AT ISSUE OR REFUND ANY SOFTWARE
|
||
LICENSE FEES OR SERVICE CHARGES PAID BY RECEIVER TO ECONET FOR SUCH
|
||
ECONET SOFTWARE.
|
||
***************************************************************/
|
||
|
||
/************************************************************************
|
||
* I N C L U D E S
|
||
*************************************************************************
|
||
*/
|
||
#include <linux/module.h>
|
||
#include <linux/types.h>
|
||
#include <linux/of_platform.h>
|
||
#include <linux/platform_device.h>
|
||
|
||
#include <asm/io.h>
|
||
|
||
/************************************************************************
|
||
* D E F I N E S & C O N S T A N T S
|
||
*************************************************************************
|
||
*/
|
||
|
||
#define CR_HSGMII_AE_PHY_BASE (0x1fa60000)
|
||
#define CR_HSGMII_AE_PHY_RANGE (0x300)
|
||
#define CR_HSGMII_AE_PHY_END (CR_HSGMII_AE_PHY_BASE + CR_HSGMII_AE_PHY_RANGE)
|
||
|
||
#define CR_HSGMII_USB_PHY_BASE (0x1fa80000)
|
||
#define CR_HSGMII_USB_PHY_RANGE (0x300)
|
||
#define CR_HSGMII_USB_PHY_END (CR_HSGMII_USB_PHY_BASE + CR_HSGMII_USB_PHY_RANGE)
|
||
|
||
#define CR_HSGMII_PCIE0_PHY_BASE (0x1fa70000)
|
||
#define CR_HSGMII_PCIE0_PHY_RANGE (0x300)
|
||
#define CR_HSGMII_PCIE0_PHY_END (CR_HSGMII_PCIE0_PHY_BASE + CR_HSGMII_PCIE0_PHY_RANGE)
|
||
|
||
#define CR_HSGMII_PCIE1_PHY_BASE (0x1fa71000)
|
||
#define CR_HSGMII_PCIE1_PHY_RANGE (0x300)
|
||
#define CR_HSGMII_PCIE1_PHY_END (CR_HSGMII_PCIE1_PHY_BASE + CR_HSGMII_PCIE1_PHY_RANGE)
|
||
|
||
|
||
/************************************************************************
|
||
* D A T A T Y P E S
|
||
*************************************************************************
|
||
*/
|
||
|
||
struct ecnt_xsi_str {
|
||
struct device *dev;
|
||
void __iomem *hsgmii_ae_base;
|
||
void __iomem *hsgmii_pcie0_base;
|
||
void __iomem *hsgmii_pcie1_base;
|
||
void __iomem *hsgmii_usb_base;
|
||
};
|
||
|
||
/************************************************************************
|
||
* STATIC VARIABLE DECLARATIONS
|
||
*************************************************************************
|
||
*/
|
||
struct ecnt_xsi_str *ecnt_xsi = NULL;
|
||
|
||
|
||
static const struct of_device_id ecnt_xsi_of_id[] = {
|
||
{ .compatible = "econet,ecnt-xsi"},
|
||
{ /* sentinel */}
|
||
};
|
||
MODULE_DEVICE_TABLE(of, ecnt_xsi_of_id);
|
||
|
||
/************************************************************************
|
||
* E X T E R N A L D A T A D E C L A R A T I O N S
|
||
*************************************************************************
|
||
*/
|
||
|
||
/************************************************************************
|
||
* F U N C T I O N D E C L A R A T I O N S
|
||
*************************************************************************
|
||
*/
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
u32 get_hsgmii_ae_data(u32 reg)
|
||
{
|
||
return readl(ecnt_xsi->hsgmii_ae_base + reg);
|
||
}
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
void set_hsgmii_ae_data(u32 reg, u32 val)
|
||
{
|
||
writel(val, ecnt_xsi->hsgmii_ae_base + reg);
|
||
}
|
||
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
u32 get_hsgmii_pcie0_data(u32 reg)
|
||
{
|
||
return readl(ecnt_xsi->hsgmii_pcie0_base + reg);
|
||
}
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
void set_hsgmii_pcie0_data(u32 reg, u32 val)
|
||
{
|
||
writel(val, ecnt_xsi->hsgmii_pcie0_base + reg);
|
||
}
|
||
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
u32 get_hsgmii_pcie1_data(u32 reg)
|
||
{
|
||
return readl(ecnt_xsi->hsgmii_pcie1_base + reg);
|
||
}
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
void set_hsgmii_pcie1_data(u32 reg, u32 val)
|
||
{
|
||
writel(val, ecnt_xsi->hsgmii_pcie1_base + reg);
|
||
}
|
||
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
u32 get_hsgmii_usb_data(u32 reg)
|
||
{
|
||
return readl(ecnt_xsi->hsgmii_usb_base + reg);
|
||
}
|
||
|
||
/* don't EXPORT this function. Create API for your purpose instead. */
|
||
void set_hsgmii_usb_data(u32 reg, u32 val)
|
||
{
|
||
writel(val, ecnt_xsi->hsgmii_usb_base + reg);
|
||
}
|
||
|
||
/* APIs */
|
||
u32 get_xsi_data(u32 reg)
|
||
{
|
||
u32 reg_phy = 0;
|
||
u32 reg_offset = 0;
|
||
|
||
/* translate addr to physical addr */
|
||
if( reg > 0xa0000000)
|
||
reg_phy = (reg & 0x1fffffff);
|
||
else
|
||
reg_phy = reg;
|
||
|
||
reg_offset = reg_phy % 4;
|
||
if(reg_offset != 0){
|
||
printk("\nDatapath(%s) get reg error, reg=0x%08X\n", __func__, reg);
|
||
return 0;
|
||
}
|
||
|
||
if( (CR_HSGMII_AE_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_AE_PHY_END) )
|
||
return get_hsgmii_ae_data(reg_phy - CR_HSGMII_AE_PHY_BASE);
|
||
else if( (CR_HSGMII_PCIE0_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_PCIE0_PHY_END) )
|
||
return get_hsgmii_pcie0_data(reg_phy - CR_HSGMII_PCIE0_PHY_BASE);
|
||
else if( (CR_HSGMII_PCIE1_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_PCIE1_PHY_END) )
|
||
return get_hsgmii_pcie1_data(reg_phy - CR_HSGMII_PCIE1_PHY_BASE);
|
||
else if( (CR_HSGMII_USB_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_USB_PHY_END) )
|
||
return get_hsgmii_usb_data(reg_phy - CR_HSGMII_USB_PHY_BASE);
|
||
else
|
||
printk("\nDatapath(%s) get reg error, reg=0x%08X\n", __func__, reg);
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(get_xsi_data);
|
||
|
||
void set_xsi_data(u32 reg, u32 val)
|
||
{
|
||
u32 reg_phy = 0;
|
||
u32 reg_offset = 0;
|
||
|
||
/* translate addr to physical addr */
|
||
if( reg > 0xa0000000)
|
||
reg_phy = (reg & 0x1fffffff);
|
||
else
|
||
reg_phy = reg;
|
||
|
||
reg_offset = reg_phy % 4;
|
||
if(reg_offset != 0){
|
||
printk("\nDatapath(%s) set reg error, reg=0x%08X\n", __func__, reg);
|
||
return 0;
|
||
}
|
||
|
||
if( (CR_HSGMII_AE_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_AE_PHY_END) )
|
||
set_hsgmii_ae_data(reg_phy - CR_HSGMII_AE_PHY_BASE, val);
|
||
else if( (CR_HSGMII_PCIE0_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_PCIE0_PHY_END) )
|
||
set_hsgmii_pcie0_data(reg_phy - CR_HSGMII_PCIE0_PHY_BASE, val);
|
||
else if( (CR_HSGMII_PCIE1_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_PCIE1_PHY_END) )
|
||
set_hsgmii_pcie1_data(reg_phy - CR_HSGMII_PCIE1_PHY_BASE, val);
|
||
else if( (CR_HSGMII_USB_PHY_BASE <= reg_phy) && (reg_phy < CR_HSGMII_USB_PHY_END) )
|
||
set_hsgmii_usb_data(reg_phy - CR_HSGMII_USB_PHY_BASE, val);
|
||
else
|
||
printk("\nDatapath(%s) set reg error, reg=0x%08X\n", __func__, reg);
|
||
|
||
}
|
||
EXPORT_SYMBOL(set_xsi_data);
|
||
|
||
struct device* get_xsi_dev(void)
|
||
{
|
||
if( (ecnt_xsi) && (ecnt_xsi->dev) )
|
||
return ecnt_xsi->dev;
|
||
else
|
||
return NULL;
|
||
}
|
||
EXPORT_SYMBOL(get_xsi_dev);
|
||
|
||
|
||
|
||
static int ecnt_xsi_probe(struct platform_device *pdev)
|
||
{
|
||
struct resource *res = NULL;
|
||
int irq = 0;
|
||
int irq_idx = 0;
|
||
|
||
if (!pdev->dev.of_node) {
|
||
dev_err(&pdev->dev, "No frame engine DT node found");
|
||
return -EINVAL;
|
||
}
|
||
|
||
ecnt_xsi = devm_kzalloc(&pdev->dev, sizeof(struct ecnt_xsi_str), GFP_KERNEL);
|
||
if (!ecnt_xsi)
|
||
return -ENOMEM;
|
||
|
||
platform_set_drvdata(pdev, ecnt_xsi);
|
||
|
||
/* get hsgmii ae base address */
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||
ecnt_xsi->hsgmii_ae_base = devm_ioremap_resource(&pdev->dev, res);
|
||
if (IS_ERR(ecnt_xsi->hsgmii_ae_base))
|
||
return PTR_ERR(ecnt_xsi->hsgmii_ae_base);
|
||
|
||
/* get hsgmii pcie0 base address */
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||
ecnt_xsi->hsgmii_pcie0_base = devm_ioremap_resource(&pdev->dev, res);
|
||
if (IS_ERR(ecnt_xsi->hsgmii_pcie0_base))
|
||
return PTR_ERR(ecnt_xsi->hsgmii_pcie0_base);
|
||
|
||
/* get hsgmii pcie1 base address */
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||
ecnt_xsi->hsgmii_pcie1_base = devm_ioremap_resource(&pdev->dev, res);
|
||
if (IS_ERR(ecnt_xsi->hsgmii_pcie1_base))
|
||
return PTR_ERR(ecnt_xsi->hsgmii_pcie1_base);
|
||
|
||
/* get hsgmii usb base address */
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
|
||
ecnt_xsi->hsgmii_usb_base = devm_ioremap_resource(&pdev->dev, res);
|
||
if (IS_ERR(ecnt_xsi->hsgmii_usb_base))
|
||
return PTR_ERR(ecnt_xsi->hsgmii_usb_base);
|
||
|
||
|
||
ecnt_xsi->dev = &pdev->dev;
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int ecnt_xsi_remove(struct platform_device *pdev)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* P L A T F O R M D R I V E R S D E C L A R A T I O N S
|
||
*************************************************************************
|
||
*/
|
||
|
||
static struct platform_driver ecnt_xsi_driver = {
|
||
.probe = ecnt_xsi_probe,
|
||
.remove = ecnt_xsi_remove,
|
||
.driver = {
|
||
.name = "ecnt-xsi",
|
||
.of_match_table = ecnt_xsi_of_id
|
||
},
|
||
};
|
||
module_platform_driver(ecnt_xsi_driver);
|
||
|
||
MODULE_DESCRIPTION("EcoNet XSI Driver");
|
||
|
||
|