1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-12-28 03:14:37 +02:00

libubb/mmcclk.c: helper functions for selecting and configuring the MMC bus clock

Experimental.
This commit is contained in:
Werner Almesberger 2013-01-07 15:19:19 -03:00
parent a593da0cd0
commit 1eb8e64811
3 changed files with 105 additions and 2 deletions

View File

@ -20,8 +20,8 @@ LIB = libubb.a
SHLIB = libubb.so
LIBVERSION = 0.0.0
OBJS = ubb.o swuart.o
HDRS = ubb/ubb.h ubb/regbase.h ubb/regs4740.h ubb/swuart.h
OBJS = ubb.o swuart.o mmcclk.o
HDRS = ubb/ubb.h ubb/regbase.h ubb/regs4740.h ubb/swuart.h ubb/mmcclk.h
.PHONY: all clean spotless

View File

@ -0,0 +1,36 @@
/*
* include/ubb/mmcclk.h - Calculate MMC bus clock speed
*
* Written 2013 by Werner Almesberger
* Copyright 2013 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef UBB_MMCCLK_H
#define UBB_MMCCLK_H
#include <stdint.h>
#define BEN_SYS_CLK_HZ 336000000
struct mmcclk {
int sys_clk_hz; /* system clock speed in Hz */
double bus_clk_hz; /* MMC bus clock in Hz */
uint32_t clkdiv; /* MSC controller clock */
uint32_t clkrt; /* bus clock divider */
};
void mmcclk_first(struct mmcclk *dsc, int sys_clk_hz);
int mmcclk_next(struct mmcclk *dsc);
void mmcclk_start(struct mmcclk *dsc);
void mmcclk_stop(void);
#endif /* !UBB_MMCCLK_H */

67
libubb/mmcclk.c Normal file
View File

@ -0,0 +1,67 @@
/*
* libubb/mmcclk.c - Calculate MMC bus clock speed
*
* Written 2013 by Werner Almesberger
* Copyright 2013 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <ubb/regs4740.h>
#include <ubb/mmcclk.h>
#define MSCCDR_MAX 32
#define CLKRT_MAX 8
#define BUS_LIMIT_MHZ 56 /* nominally, the limit is 20 MHz */
static int calculate_clock(struct mmcclk *dsc)
{
dsc->bus_clk_hz = dsc->sys_clk_hz/(dsc->clkdiv+1.0)/(1 << dsc->clkrt);
return dsc->bus_clk_hz <= BUS_LIMIT_MHZ*1000000;
}
void mmcclk_first(struct mmcclk *dsc, int sys_clk_hz)
{
dsc->sys_clk_hz = sys_clk_hz ? sys_clk_hz : BEN_SYS_CLK_HZ;
dsc->clkdiv = dsc->clkrt = 0;
if (calculate_clock(dsc))
return;
mmcclk_next(dsc);
}
int mmcclk_next(struct mmcclk *dsc)
{
while (1) {
if (++dsc->clkdiv == MSCCDR_MAX) {
dsc->clkdiv = 0;
if (++dsc->clkrt == CLKRT_MAX)
return 0;
}
if (calculate_clock(dsc))
return 1;
}
}
void mmcclk_start(struct mmcclk *dsc)
{
MSCCDR = dsc->clkdiv; /* set controller clock */
CLKGR &= ~(1 << 7); /* enable MSC clock */
MSC_CLKRT = dsc->clkrt; /* set bus clock */
MSC_STRPCL = 2; /* start MMC bus clock output */
}
void mmcclk_stop(void)
{
MSC_STRPCL = 1; /* stop MMC bus clock output */
}