我是靠谱客的博主 微笑狗,最近开发中收集的这篇文章主要介绍board-dt-sama5.c(arch\arm\mach-at91),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

/*
 *  Setup code for SAMA5 Evaluation Kits with Device Tree support
 *
 *  Copyright (C) 2013 Atmel,
 *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
 *
 * Licensed under GPLv2 or later.
 */


#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/micrel_phy.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/phy.h>


#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/firmware.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <linux/of_address.h>


#include "at91_aic.h"
#include "generic.h"
#include "clock.h"


/************************************/
/* TEMPORARY NON-DT STUFF FOR MIURA */
/************************************/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <video/atmel_lcdfb.h>
#include <mach/atmel_hlcdc.h>
#include <media/soc_camera.h>
#include <media/atmel-isi.h>


#define LINK_SENSOR_MODULE_TO_SOC_CAMERA(_sensor_name, _soc_camera_id, _i2c_adapter_id)
static struct soc_camera_desc iclink_##_sensor_name = {
.subdev_desc = {
.power = i2c_camera_power,
.query_bus_param = isi_camera_query_bus_param,
},
.host_desc = {
.bus_id = -1,
.board_info = &i2c_##_sensor_name,
.i2c_adapter_id = _i2c_adapter_id,
},
};
static struct platform_device isi_##_sensor_name = {
.name = "soc-camera-pdrv",
.id = _soc_camera_id,
.dev = {
.platform_data = &iclink_##_sensor_name,
},
};


/*
 * LCD Controller
 */
static char lcd_type[12];
static int __init lcd_type_init(char* s) {
        printk("lcd_type_init %sn", s); 
        strncpy(lcd_type, s, 12);
        return 0;
}
__setup("dispmode=", lcd_type_init);




static struct fb_videomode at91_tft_vga_modes_800_480[] = {
{
.name = "LCD800x480 @ 60",
.refresh = 60,
.xres = 800, .yres = 480,
.pixclock = KHZ2PICOS(44000),


.left_margin = 48, .right_margin = 40,
.upper_margin = 3, .lower_margin = 29,
.hsync_len = 128, .vsync_len = 3,


.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
};


static struct fb_videomode at91_tft_vga_modes_640_480[] = {
{
.name = "LCD640x480 @ 60",
.refresh = 60,
.xres = 640, .yres = 480,
.pixclock = KHZ2PICOS(39700),


.left_margin = 134, .right_margin = 16,
.upper_margin = 11, .lower_margin = 32,
.hsync_len = 10, .vsync_len = 2,


.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
};


static struct fb_videomode at91_tft_vga_modes_480_272[] = {
        {
                .name           = "LCD480x272 @ 60 AT043TN24",
                .refresh        = 60,
                .xres           = 480,
                .yres           = 272,
                .pixclock       = KHZ2PICOS(9000),
                .left_margin    = 2,
                .right_margin   = 2,
                .upper_margin   = 2,
                .lower_margin   = 2,
                .hsync_len      = 41,
                .vsync_len      = 10,
        //        .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
                .vmode          = FB_VMODE_NONINTERLACED,
        },
};


static struct fb_videomode at91_tft_vga_modes_320_240[] = {
        {
                .name           = "LCD320x240@60",
                .refresh        = 60,
                .xres           = 320,
                .yres           = 240,
                .pixclock       = KHZ2PICOS(6400),
                .left_margin    = 69,
                .right_margin   = 18,
                .upper_margin   = 12,
                .lower_margin   = 10,
                .hsync_len      = 1,
                .vsync_len      = 1,
//                .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
                .vmode          = FB_VMODE_NONINTERLACED,
        },
};
static struct fb_monspecs at91fb_default_monspecs = {
.manufacturer = "LG",
.monitor = "LB043WQ1",


.modedb = at91_tft_vga_modes_640_480,
.modedb_len = ARRAY_SIZE(at91_tft_vga_modes_640_480),
.hfmin = 15000,
.hfmax = 17640,
.vfmin = 57,
.vfmax = 67,
};


/* Default output mode is TFT 24 bit */
#define BPP_OUT_DEFAULT_LCDCFG5 (LCDC_LCDCFG5_MODE_OUTPUT_16BPP)


/* Driver datas */
static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
.lcdcon_is_backlight = true,
.alpha_enabled = false,
.default_bpp = 16,
/* Reserve enough memory for 32bpp */
// .smem_len = 800 * 480 * 4,
.smem_len = 640 * 480 * 4,
/* default_lcdcon2 is used for LCDCFG5 */
.default_lcdcon2 = BPP_OUT_DEFAULT_LCDCFG5,
.default_monspecs = &at91fb_default_monspecs,
.guard_time = 9,
.lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB,
};


/*
 *  ISI
 */
static struct isi_platform_data isi_data = {
.frate = ISI_CFG1_FRATE_CAPTURE_ALL,
/* to use codec and preview path simultaneously */
.full_mode = 1,
.data_width_flags = ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10,
/* ISI_MCK is provided by programmable clock or external clock */
.mck_hz = 25000000,
};


static struct clk_lookup isi_mck_lookups[] = {
CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi", NULL),
};


void __init at91_config_isi(bool use_pck_as_mck, const char *pck_id)
{
struct clk *pck;
struct clk *parent;


if (use_pck_as_mck) {
pck = clk_get(NULL, pck_id);
parent = clk_get(NULL, "plla");


BUG_ON(IS_ERR(pck) || IS_ERR(parent));


if (clk_set_parent(pck, parent)) {
pr_err("Failed to set PCK's parentn");
} else {
/* Register PCK as ISI_MCK */
isi_mck_lookups[0].clk = pck;
clkdev_add_table(isi_mck_lookups,
ARRAY_SIZE(isi_mck_lookups));
}


clk_put(pck);
clk_put(parent);
}
}


static unsigned int camera_reset_pin;
static unsigned int camera_power_pin;
static void camera_set_gpio_pins(uint reset_pin, uint power_pin)
{
camera_reset_pin = reset_pin;
camera_power_pin = power_pin;
}


/*
 * soc-camera OV2640
 */
static unsigned long isi_camera_query_bus_param(struct soc_camera_subdev_desc *link)
{
/* ISI board for ek using default 8-bits connection */
return SOCAM_DATAWIDTH_8;
}


static int i2c_camera_power(struct device *dev, int on)
{
int res, ret = 0;


pr_debug("%s: %s the cameran", __func__, on ? "ENABLE" : "DISABLE");


res = devm_gpio_request(dev, camera_power_pin, "ov2640_power");
if (res < 0) {
printk("can't request ov2640_power pinn");
return -1;
}


res = devm_gpio_request(dev, camera_reset_pin, "ov2640_reset");
if (res < 0) {
printk("can't request ov2640_reset pinn");
devm_gpio_free(dev, camera_power_pin);
return -1;
}


/* enable or disable the camera */
res = gpio_direction_output(camera_power_pin, !on);
if (res < 0) {
printk("can't request output direction for ov2640_power pinn");
ret = -1;
goto out;
}


if (!on)
goto out;


/* If enabled, give a reset impulse */
res = gpio_direction_output(camera_reset_pin, 0);
if (res < 0) {
printk("can't request output direction for ov2640_reset pinn");
ret = -1;
goto out;
}
msleep(20);
res = gpio_direction_output(camera_reset_pin, 1);
if (res < 0) {
printk("can't request output direction for ov2640_reset pinn");
ret = -1;
goto out;
}
msleep(100);


out:
devm_gpio_free(dev, camera_reset_pin);
devm_gpio_free(dev, camera_power_pin);
return ret;
}


static struct i2c_board_info i2c_ov2640 = {
I2C_BOARD_INFO("ov2640", 0x30),
};
static struct i2c_board_info i2c_ov5642 = {
I2C_BOARD_INFO("ov5642", 0x3c),
};
static struct i2c_board_info i2c_ov9740 = {
I2C_BOARD_INFO("ov9740", 0x10),
};
static struct i2c_board_info i2c_ov7740 = {
I2C_BOARD_INFO("ov7740", 0x21),
};


LINK_SENSOR_MODULE_TO_SOC_CAMERA(ov2640, 0, 1);
LINK_SENSOR_MODULE_TO_SOC_CAMERA(ov5642, 1, 1);
LINK_SENSOR_MODULE_TO_SOC_CAMERA(ov9740, 2, 1);
LINK_SENSOR_MODULE_TO_SOC_CAMERA(ov7740, 3, 1);


static struct platform_device *sensors[] __initdata = {
&isi_ov2640,
&isi_ov5642, /* compatible for ov5640 */
&isi_ov9740,
&isi_ov7740,
};


static void at91_fixup_isi_sensor_bus(struct platform_device **sensors,
unsigned int sensors_nbr, unsigned int fixed_i2c_id)
{
int i;
struct platform_device **s;
struct soc_camera_desc *scd;


s = sensors;
for (i = 0; i < sensors_nbr; i++) {
if (s[i]) {
scd = s[i]->dev.platform_data;
if (scd)
scd->host_desc.i2c_adapter_id = fixed_i2c_id;
} else {
break;
}
}
}


struct of_dev_auxdata at91_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf8038000, "atmel_hlcdfb_base", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf8038100, "atmel_hlcdfb_ovl1", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf0030000, "atmel_hlcdfb_base", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf0030140, "atmel_hlcdfb_ovl1", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf0030240, "atmel_hlcdfb_ovl2", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9g45-isi", 0xf0034000, "atmel_isi", &isi_data),
OF_DEV_AUXDATA("atmel,at91sam9g45-isi", 0xf0008000, "atmel_isi", &isi_data),
/* SAMA5D4 */
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf0000000, "atmel_hlcdfb_base", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf0000140, "atmel_hlcdfb_ovl1", &ek_lcdc_data),
OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf0000240, "atmel_hlcdfb_ovl2", &ek_lcdc_data),
{ /* sentinel */ }
};


static const struct of_device_id irq_of_match[] __initconst = {


{ .compatible = "atmel,sama5d3-aic", .data = sama5d3_aic5_of_init },
{ .compatible = "atmel,sama5d4-aic", .data = sama5d4_aic5_of_init },
{ /*sentinel*/ }
};


static void __init at91_dt_init_irq(void)
{
of_irq_init(irq_of_match);
}


static int ksz9021rn_phy_fixup(struct phy_device *phy)
{
int value;


#define GMII_RCCPSR 260
#define GMII_RRDPSR 261
#define GMII_ERCR 11
#define GMII_ERDWR 12


/* Set delay values */
value = GMII_RCCPSR | 0x8000;
phy_write(phy, GMII_ERCR, value);
value = 0xF2F4;
phy_write(phy, GMII_ERDWR, value);
value = GMII_RRDPSR | 0x8000;
phy_write(phy, GMII_ERCR, value);
value = 0x2222;
phy_write(phy, GMII_ERDWR, value);


return 0;
}


static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
{
phy_write(dev, 0x0d, device);
phy_write(dev, 0x0e, reg);
phy_write(dev, 0x0d, (1 << 14) | device);
phy_write(dev, 0x0e, val);
}


static int ksz9031rn_phy_fixup(struct phy_device *dev)
{
/*
* min rx data delay, max rx/tx clock delay,
* min rx/tx control delay
*/
/*
mmd_write_reg(dev, 2, 4, 0);
mmd_write_reg(dev, 2, 5, 0);
mmd_write_reg(dev, 2, 8, 0x003ff);
*/
mmd_write_reg(dev, 2, 4, 0x84);
mmd_write_reg(dev, 2, 5, 0x4444);
mmd_write_reg(dev, 2, 8, 0x1ef);


return 0;
}


static int ksz8081_phy_reset(struct phy_device *phy)
{
int value;


/*
* As disconnect the hardware reset, so use software reset
*
* The basic control (register 0) bit 15 is software reset
*/
value = phy_read(phy, 0);
value |= (1 << 15);
phy_write(phy, 0, value);


return 0;
}


#ifdef CONFIG_CACHE_L2X0
static void __init at91_init_l2cache(void)
{
struct device_node *np;
void __iomem *l2cc_base;
u32 reg;
int ret;


np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
if (!np)
return;


l2cc_base = of_iomap(np, 0);
if (!l2cc_base)
panic("unable to map l2cc cpu registersn");


of_node_put(np);


ret = call_firmware_op(l2x0_init);
if (ret == -ENOSYS) {
/* Disable cache if it hasn't been done yet */
if (readl_relaxed(l2cc_base + L2X0_CTRL) & L2X0_CTRL_EN)
writel_relaxed(~L2X0_CTRL_EN, l2cc_base + L2X0_CTRL);


/* Prefetch Control */
reg = readl_relaxed(l2cc_base + L2X0_PREFETCH_CTRL);
reg &= ~L2X0_PCR_OFFSET_MASK;
reg |= L2X0_PCR_OFFSET_(0x01);
reg |= L2X0_PCR_IDLEN;
reg |= L2X0_PCR_PDEN;
reg |= L2X0_PCR_DATPEN;
reg |= L2X0_PCR_INSPEN;
reg |= L2X0_PCR_DLEN;
writel_relaxed(reg, l2cc_base + L2X0_PREFETCH_CTRL);


/* Power Control */
reg = readl_relaxed(l2cc_base + L2X0_POWER_CTRL);
reg |= L2X0_STNDBY_MODE_EN;
reg |= L2X0_DYNAMIC_CLK_GATING_EN;
writel_relaxed(reg, l2cc_base + L2X0_POWER_CTRL);


/* Disable interrupts */
writel_relaxed(0x00, l2cc_base + L2X0_INTR_MASK);
writel_relaxed(0x01ff, l2cc_base + L2X0_INTR_CLEAR);


l2x0_of_init(0, ~0UL);
} else {
outer_cache.disable = firmware_ops->l2x0_disable;
}
}
#else
static inline void at91_init_l2cache(void) {}
#endif


static void __init sama5_dt_device_init(void)
{
struct device_node *np;


at91_init_l2cache();


if (of_machine_is_compatible("atmel,sama5d3xcm") &&
    IS_ENABLED(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
} else if (of_machine_is_compatible("atmel,sama5d3-xplained") &&
    IS_ENABLED(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
ksz9031rn_phy_fixup);
} else if (of_machine_is_compatible("atmel,sama5d4ek") &&
    IS_ENABLED(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
ksz8081_phy_reset);
}


np = of_find_compatible_node(NULL, NULL, "atmel,at91sam9g45-isi");
if (np) {
if (of_device_is_available(np)) {
if (of_machine_is_compatible("atmel,sama5d3xmb")) {
camera_set_gpio_pins(AT91_PIN_PE24, AT91_PIN_PE29);
at91_config_isi(true, "pck1");
} else if (of_machine_is_compatible("atmel,sama5d4ek")) {
at91_fixup_isi_sensor_bus(sensors, ARRAY_SIZE(sensors), 0);
camera_set_gpio_pins(AT91_PIN_PB11, AT91_PIN_PB5);
at91_config_isi(true, "pck1");
}
}
}
#if 0
/* Hack for PDA display modules to update lcd settings */
if (of_machine_is_compatible("pda,tm70xx")) {
__u8 manufacturer[4] = "PALM";
__u8 monitor[14] = "AT07";


/* set LCD configuration */
at91_tft_vga_modes[0].name = "PALM";
at91_tft_vga_modes[0].left_margin = 128;
at91_tft_vga_modes[0].right_margin = 0;
at91_tft_vga_modes[0].upper_margin = 23;
at91_tft_vga_modes[0].lower_margin = 22;
at91_tft_vga_modes[0].hsync_len = 5;
at91_tft_vga_modes[0].vsync_len = 5;


memcpy(at91fb_default_monspecs.manufacturer, manufacturer, 4);
memcpy(at91fb_default_monspecs.monitor, monitor, 14);


ek_lcdc_data.default_lcdcon2 = LCDC_LCDCFG5_MODE_OUTPUT_18BPP;


printk("LCD parameters updated for PDA7 display modulen");
}
if (of_machine_is_compatible("pda,tm43xx")) {
__u8 manufacturer[4] = "Inlx";
__u8 monitor[14] = "AT043TN24";


/* set LCD configuration */
at91_tft_vga_modes[0].name = "Inlx";
at91_tft_vga_modes[0].xres = 480;
at91_tft_vga_modes[0].yres = 272;
at91_tft_vga_modes[0].pixclock = KHZ2PICOS(9000);
at91_tft_vga_modes[0].left_margin = 2;
at91_tft_vga_modes[0].right_margin = 2;
at91_tft_vga_modes[0].upper_margin = 2;
at91_tft_vga_modes[0].lower_margin = 2;
at91_tft_vga_modes[0].hsync_len = 41;
at91_tft_vga_modes[0].vsync_len = 11;


memcpy(at91fb_default_monspecs.manufacturer, manufacturer, 4);
memcpy(at91fb_default_monspecs.monitor, monitor, 14);


ek_lcdc_data.smem_len = 480 * 272 * 4;


printk("LCD parameters updated for PDA4 display modulen");
}
#endif
{
                /* LCD Controller */
                if(!strcmp(lcd_type,"3.5inch_LCD"))
                {   
                        ek_lcdc_data.smem_len = 320 * 240 * 4;
                        at91fb_default_monspecs.modedb = at91_tft_vga_modes_320_240;
                        at91fb_default_monspecs.modedb_len = ARRAY_SIZE(at91_tft_vga_modes_320_240);
                }   
                else if(!strcmp(lcd_type,"4.3inch_LCD"))
                {   
                        ek_lcdc_data.smem_len = 480 * 272 * 4;
                        at91fb_default_monspecs.modedb = at91_tft_vga_modes_480_272;
                        at91fb_default_monspecs.modedb_len = ARRAY_SIZE(at91_tft_vga_modes_480_272);
                }   
                else if(!strcmp(lcd_type,"5.6inch_LCD"))
                {   
                        ek_lcdc_data.smem_len = 640 * 480 * 4;
                        at91fb_default_monspecs.modedb = at91_tft_vga_modes_640_480;
                        at91fb_default_monspecs.modedb_len = ARRAY_SIZE(at91_tft_vga_modes_640_480);
                }   
                else if(!strcmp(lcd_type,"7inch_LCD"))
                {   
                        ek_lcdc_data.smem_len = 800 * 480 * 4;
                        at91fb_default_monspecs.modedb = at91_tft_vga_modes_800_480;
                        at91fb_default_monspecs.modedb_len = ARRAY_SIZE(at91_tft_vga_modes_800_480);
                }   
}

of_platform_populate(NULL, of_default_bus_match_table, at91_auxdata_lookup, NULL);
platform_add_devices(sensors, ARRAY_SIZE(sensors));
}


static const char * sama5_dt_board_compat[] __initdata = {
" atmel,sama5",
NULL
};


DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)")
/* Maintainer: Atmel */
.init_time = at91sam926x_pit_init,
.map_io = at91_map_io,
.handle_irq = at91_aic5_handle_irq,
.init_early = at91_dt_initialize,
.init_irq = at91_dt_init_irq,
.init_machine = sama5_dt_device_init,
.dt_compat = sama5_dt_board_compat,
MACHINE_END


static const char *sama5_alt_dt_board_compat[] __initdata = {
"atmel,sama5d4",
NULL
};


DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5 (Device Tree)")
/* Maintainer: Atmel */
.init_time = at91sam926x_pit_init,
.map_io = at91_alt_map_io,
.handle_irq = at91_aic5_handle_irq,
.init_early = at91_alt_dt_initialize,
.init_irq = at91_dt_init_irq,
.init_machine = sama5_dt_device_init,
.dt_compat = sama5_alt_dt_board_compat,
MACHINE_END

最后

以上就是微笑狗为你收集整理的board-dt-sama5.c(arch\arm\mach-at91)的全部内容,希望文章能够帮你解决board-dt-sama5.c(arch\arm\mach-at91)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部