BeagleBoard-xMでPWM出力する(3)

20ms周期でパルス幅10msの波形出力するプログラムの完成形といってもテストプログラムレベルです。

// GPIO_144(GPT_9)を使用
// Expansion Connector 4pin
#define CONTROL_PADCONF_GPIO_144_L (0x48002174)

#define GPT_9 0x49040000
#define TIOCP_CFG 0x010
#define TCLR 0x024
#define TCRR 0x028
#define TLDR 0x02C
#define TMAR 0x038
#define GPT_9_TLDR 0x4904002C

#define SMART_IDLE 0x00000010
#define IDLE_MASK 0x00000018

#define AR_AR 0x00000002
#define TRG_OF 0x00000400
#define TRG_OFM 0x00000800
#define PT_TGL 0x00001000
#define ST_ST 0x00000001
#define CE_EN 0x00000040

#define PRCM_CM_CLKSEL_PER 0x48005040
#define CLKSEL_GPT9 0x00000080

#define PRCM_CM_FCLKEN_PER 0x48005000
#define EN_GPT9 0x00000400

// [2]:0=logic off 1=on [1:0]:00=off 01=RETENTION 10=INACTIVE 11:on
#define PRCM_PM_PWSTST_PER 0x483070E4

// [0]:0=no clock 1=clock active
#define PRCM_CM_CLKSTST_PER 0x4800504C

// [10]:0:can be access 1:can not be access
#define PRCM_CM_IDLEST_PER 0x48005020

// 0x0:12 MHz 0x1:13 MHz 0x2:19.2 MHz 0x3:26 MHz 0x4:38.4 MHz 0x5:16.8 MHz
#define PRM_CLKSEL 0x48306D40

long unsigned int v;
long unsigned int ld;
long unsigned int lds;
long unsigned int lda;

volatile unsigned long * adr;
int i;

// GPIO_144(GPT_9)を使用
// Expansion Connector 4pin

v = __raw_readl(ioremap(PRM_CLKSEL,SZ_8K));
printk( KERN_INFO "PRM_CLKSEL = %08lx\n",v );

// CLKの指定
// GPT9の場合
// PRCM.CM_CLKSEL_PER[7]をオン
v = __raw_readl(ioremap(PRCM_CM_CLKSEL_PER,SZ_8K));
printk( KERN_INFO "PRCM_CM_CLKSEL_PER = %08lx\n",v );
v |= CLKSEL_GPT9;
__raw_writel(v,ioremap(PRCM_CM_CLKSEL_PER,SZ_8K));
v = __raw_readl(ioremap(PRCM_CM_CLKSEL_PER,SZ_8K));
printk( KERN_INFO "PRCM_CM_CLKSEL_PER = %08lx\n",v );

// PRCM.CM_FCLKEN_PER[10]をオン
v = __raw_readl(ioremap(PRCM_CM_FCLKEN_PER,SZ_8K));
printk( KERN_INFO "PRCM_CM_FCLKEN_PER = %08lx\n",v );
v |= EN_GPT9;
__raw_writel(v,ioremap(PRCM_CM_FCLKEN_PER,SZ_8K));
v = __raw_readl(ioremap(PRCM_CM_FCLKEN_PER,SZ_8K));
printk( KERN_INFO "PRCM_CM_FCLKEN_PER = %08lx\n",v );

v = __raw_readl(ioremap(PRCM_PM_PWSTST_PER,SZ_8K));
printk( KERN_INFO "PRCM_PM_PWSTST_PER = %08lx\n",v );

v = __raw_readl(ioremap(PRCM_CM_CLKSTST_PER,SZ_8K));
printk( KERN_INFO "PRCM_CM_CLKSTST_PER = %08lx\n",v );

for(i=0;i<10000;i++){
v = __raw_readl(ioremap(PRCM_CM_IDLEST_PER,SZ_8K));
printk( KERN_INFO "PRCM_CM_IDLEST_PER = %08lx\n",v );
if(!(v&0x00000400))break;
}

v = __raw_readl(ioremap(GPT_9+TIOCP_CFG,SZ_8K));
printk( KERN_INFO "GPT9+TIOCP_CFG = %08lx\n",v );
v &= ~IDLE_MASK;
v |= SMART_IDLE;
__raw_writel(v,ioremap(GPT_9+TIOCP_CFG,SZ_8K));
v = __raw_readl(ioremap(GPT_9+TIOCP_CFG,SZ_8K));
printk( KERN_INFO "GPT9+TIOCP_CFG = %08lx\n",v );

// CONTROL_PADCONF_xの設定
// MUXMODEを2に設定
v = __raw_readl(ioremap(CONTROL_PADCONF_GPIO_144_L,SZ_8K));
v &= 0xffff0000;
v |= 2;
__raw_writel(v,ioremap(CONTROL_PADCONF_GPIO_144_L,SZ_8K));
v = __raw_readl(ioremap(CONTROL_PADCONF_GPIO_144_L,SZ_8K));
printk( KERN_INFO "CONTROL_PADCONF_GPIO_144_L = %08lx\n",v );
v = 0;
__raw_writel(v,ioremap(GPT_9+TCLR,4096));

// ロードレジスタの設定
// TLDR = 0xffffffff - 0x7fe40
adr = ioremap(GPT_9_TLDR,4096);
printk( KERN_INFO "GPT_9+TLDR adr = %08lx\n",adr );
v = *adr;
printk( KERN_INFO "GPT_9+TLDR = %08lx\n",v );
ld = 0xffffffff - 0x3f7a0;
*adr = ld;
v = *adr;
printk( KERN_INFO "GPT_9+TLDR = %08lx\n",v );

// TCRR = TLDR
__raw_writel(ld,ioremap(GPT_9+TCRR,SZ_8K));

// マッチレジスタの設定
ld = ld + 0x1fbd0;
__raw_writel(ld,ioremap(GPT_9+TMAR,SZ_8K));

// オートリロードモード設定
// TCLR[1]AR = 1
v = AR_AR;

// オーバーフロー&マッチモード設定
// TCLR[11:10]TRG = 0b10
v |= TRG_OFM;

// トグルモード設定
// TCLR[12]PT = 1
v |= PT_TGL;
// コンペアイネーブル
v |= CE_EN;
__raw_writel(v,ioremap(GPT_9+TCLR,4096));

// タイマースタート
// TCLR[0]ST = 1
v |= ST_ST;
__raw_writel(v,ioremap(GPT_9+TCLR,SZ_8K));
v = __raw_readl(ioremap(GPT_9+TCLR,SZ_8K));
printk( KERN_INFO "GPT_9+TCLR = %08lx\n",v );