星期四, 十一月 01, 2007

SPI子系统分析『转』

2.6.18内核下已经添加了完整的spi子系统了,参考mtd的分析,将从下到上层,再从上到下层的对其进行分析。

以下先从下到上的进行分析:
driver/spi下有两个底层相关的spi驱动程序:
spi_s3c24xx.c和spi_s3c24xx_gpio.c

其中spi_s3c24xx.c是基于s3c24xx下相应的spi接口的驱动程序,spi_s3c24xx_gpio.c允许用户指定3个gpio口,分别充当spi_clk、spi_mosi和spi_miso接口,模拟标准的spi总线。
s3c2410自带了两个spi接口(spi0和spi1),在此我只研究基于s3c2410下spi接口的驱动程序spi_s3c24xx.c。
首先从spi驱动的检测函数进行分析:
static int s3c24xx_spi_probe(struct platform_device *pdev)
{
struct s3c24xx_spi *hw;
struct spi_master *master;
struct spi_board_info *bi;
struct resource *res;
int err = 0;
int i;

/* pi_alloc_master函数申请了struct spi_master+struct s3c24xx_spi大小的数据,
* spi_master_get_devdata和pi_master_get分别取出struct s3c24xx_spi和struct spi_master结构指针
*/
master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
if (master == NULL) {
dev_err(&pdev->dev, "No memory for spi_master\n");
err = -ENOMEM;
goto err_nomem;
}

/* 填充struct spi_master结构 */
hw = spi_master_get_devdata(master);
memset(hw, 0, sizeof(struct s3c24xx_spi));

hw->master = spi_master_get(master);
hw->pdata = pdev->dev.platform_data;
hw->dev = &pdev->dev;

if (hw->pdata == NULL) {
dev_err(&pdev->dev, "No platform data supplied\n");
err = -ENOENT;
goto err_no_pdata;
}

platform_set_drvdata(pdev, hw);//dev_set_drvdata(&pdev->dev, hw)
init_completion(&hw->done);

/* setup the state for the bitbang driver */

/* 填充hw->bitbang结构(hw->bitbang结构充当一个中间层,相当与input system的input_handle struct) */
hw->bitbang.master = hw->master;
hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
hw->bitbang.chipselect = s3c24xx_spi_chipsel;
hw->bitbang.txrx_bufs = s3c24xx_spi_txrx;
hw->bitbang.master->setup = s3c24xx_spi_setup;

dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);

/* find and map our resources */
/* 申请spi所用到的资源:io、irq、时钟等 */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
err = -ENOENT;
goto err_no_iores;
}

hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,
pdev->name);

if (hw->ioarea == NULL) {
dev_err(&pdev->dev, "Cannot reserve region\n");
err = -ENXIO;
goto err_no_iores;
}

hw->regs = ioremap(res->start, (res->end - res->start)+1);
if (hw->regs == NULL) {
dev_err(&pdev->dev, "Cannot map IO\n");
err = -ENXIO;
goto err_no_iomap;
}

hw->irq = platform_get_irq(pdev, 0);
if (hw->irq <>dev, "No IRQ specified\n");
err = -ENOENT;
goto err_no_irq;
}

err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
if (err) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto err_no_irq;
}

hw->clk = clk_get(&pdev->dev, "spi");
if (IS_ERR(hw->clk)) {
dev_err(&pdev->dev, "No clock for device\n");
err = PTR_ERR(hw->clk);
goto err_no_clk;
}

/* for the moment, permanently enable the clock */

clk_enable(hw->clk);

/* program defaults into the registers */
/* 初始化spi相关的寄存器 */
writeb(0xff, hw->regs + S3C2410_SPPRE);
writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
/* add by lfc */
s3c2410_gpio_setpin(S3C2410_GPE13, 0);
s3c2410_gpio_setpin(S3C2410_GPE12, 0);
s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_SPICLK0);
s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPE12_SPIMOSI0);
s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_SPIMISO0);
/* end add */

/* setup any gpio we can */
/* 片选 */
if (!hw->pdata->set_cs) {
s3c2410_gpio_setpin(hw->pdata->pin_cs, 1);
s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT);
}

/* register our spi controller */
/* 最终通过调用spi_register_master来注册spi控制器(驱动) */
err = spi_bitbang_start(&hw->bitbang);
if (err) {
dev_err(&pdev->dev, "Failed to register SPI master\n");
goto err_register;
}

dev_dbg(hw->dev, "shutdown=%d\n", hw->bitbang.shutdown);

/* register all the devices associated */
/* 注册所用使用本spi驱动的设备 */

bi = &hw->pdata->board_info[0];
for (i = 0; i <>pdata->board_size; i++, bi++) {
dev_info(hw->dev, "registering %s\n", bi->modalias);

bi->controller_data = hw;
spi_new_device(master, bi);
}

return 0;

err_register:
clk_disable(hw->clk);
clk_put(hw->clk);

err_no_clk:
free_irq(hw->irq, hw);

err_no_irq:
iounmap(hw->regs);

err_no_iomap:
release_resource(hw->ioarea);
kfree(hw->ioarea);

err_no_iores:
err_no_pdata:
spi_master_put(hw->master);;

err_nomem:
return err;
}

/*
* spi_alloc_master - allocate SPI master controller
* @dev: the controller, possibly using the platform_bus
* @size: how much driver-private data to preallocate; the pointer to this
* memory is in the class_data field of the returned class_device,
* accessible with spi_master_get_devdata().
*
* This call is used only by SPI master controller drivers, which are the
* only ones directly touching chip registers. It's how they allocate
* an spi_master structure, prior to calling spi_register_master().
*
* This must be called from context that can sleep. It returns the SPI
* master structure on success, else NULL.
*
* The caller is responsible for assigning the bus number and initializing
* the master's methods before calling spi_register_master(); and (after errors
* adding the device) calling spi_master_put() to prevent a memory leak.
*/
/*注释已经写得很清楚了,本函数旨在分配spi_master struct
*其中,device为主控制设备,size为需要预分配的设备私有数据大小
*该函数被spi主控制器驱动所调用,用于在调用spi_register_master注册主控制器前
*分配spi_master struct,分配bus number和初始化主控制器的操作方法
*注意在分配spi_master struct的时候多分配了大小为size的设备私有数据
*并通过spi_master_set_devdata函数把其放到class_data field里,以后可以通过spi_master_get_devdata来访问
*/
struct spi_master * __init_or_module
spi_alloc_master(struct device *dev, unsigned size)
{
struct spi_master *master;

if (!dev)
return NULL;

master = kzalloc(size + sizeof *master, SLAB_KERNEL);
if (!master)
return NULL;

class_device_initialize(&master->cdev);
master->cdev.class = &spi_master_class;
master->cdev.dev = get_device(dev);
spi_master_set_devdata(master, &master[1]);

return master;
}


/*
* spi_bitbang_start - start up a polled/bitbanging SPI master driver
* @bitbang: driver handle
*
* Caller should have zero-initialized all parts of the structure, and then
* provided callbacks for chip selection and I/O loops. If the master has
* a transfer method, its final step should call spi_bitbang_transfer; or,
* that's the default if the transfer routine is not initialized. It should
* also set up the bus number and number of chipselects.
*
* For i/o loops, provide callbacks either per-word (for bitbanging, or for
* hardware that basically exposes a shift register) or per-spi_transfer
* (which takes better advantage of hardware like fifos or DMA engines).
*
* Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and
* spi_bitbang_cleanup to handle those spi master methods. Those methods are
* the defaults if the bitbang->txrx_bufs routine isn't initialized.
*
* This routine registers the spi_master, which will process requests in a
* dedicated task, keeping IRQs unblocked most of the time. To stop
* processing those requests, call spi_bitbang_stop().
*/
int spi_bitbang_start(struct spi_bitbang *bitbang)
{
int status;

if (!bitbang->master || !bitbang->chipselect)
return -EINVAL;
/*bitbang_work
* 初始化a work,后面再create_singlethread_workqueue,
* 等到有数据要传输的时候,在spi_bitbang_transfer函数中通过调用queue_work(bitbang->workqueue, &bitbang->work)
* 把work扔进workqueue中调度运行
* 这是内核的一贯做法,在mmc/sd驱动中也是这样处理的^_^
*/
INIT_WORK(&bitbang->work, bitbang_work, bitbang);

/* 初始化自旋锁和链表头,以后用到 */
spin_lock_init(&bitbang->lock);
spi_new_device INIT_LIST_HEAD(&bitbang->queue);

if (!bitbang->master->transfer)
bitbang->master->transfer = spi_bitbang_transfer;//spi数据的传输就是通过调用这个方法来实现的
/* spi_s3c24xx.c驱动中有相应的txrx_bufs处理方法,在bitbang_work中被调用 */
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs;
if (!bitbang->master->setup) {
if (!bitbang->setup_transfer)
bitbang->setup_transfer =
spi_bitbang_setup_transfer;
bitbang->master->setup = spi_bitbang_setup;
bitbang->master->cleanup = spi_bitbang_cleanup;
}
/* spi_s3c24xx.c驱动中有相应的setup处理方法,在稍后的spi_new_device中被调用 */
} else if (!bitbang->master->setup)
return -EINVAL;

/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
/* 创建工作者进程 */
bitbang->workqueue = create_singlethread_workqueue(
bitbang->master->cdev.dev->bus_id);
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
}

/* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices
*/
status = spi_register_master(bitbang->master);
if (status <>workqueue);
err1:
return status;
}


/**
* spi_register_master - register SPI master controller
* @master: initialized master, originally from spi_alloc_master()
*
* SPI master controllers connect to their drivers using some non-SPI bus,
* such as the platform bus. The final stage of probe() in that code
* includes calling spi_register_master() to hook up to this SPI bus glue.
*
* SPI controllers use board specific (often SOC specific) bus numbers,
* and board-specific addressing for SPI devices combines those numbers
* with chip select numbers. Since SPI does not directly support dynamic
* device identification, boards need configuration tables telling which
* chip is at which address.
*
* This must be called from context that can sleep. It returns zero on
* success, else a negative error code (dropping the master's refcount).
* After a successful return, the caller is responsible for calling
* spi_unregister_master().
*/
int __init_or_module
spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) dev =" master-">cdev.dev;
int status = -ENODEV;
int dynamic = 0;

if (!dev)
return -ENODEV;

/* convention: dynamically assigned bus IDs count down from the max */
if (master->bus_num <>bus_num = atomic_dec_return(&dyn_bus_id);
dynamic = 1;
}

/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
"spi%u", master->bus_num);
status = class_device_add(&master->cdev);//注册设备
if (status <>cdev.class_id,
dynamic ? " (dynamic)" : "");

/* populate children from any spi device tables */
scan_boardinfo(master);
status = 0;
done:
return status;
}


/* FIXME someone should add support for a __setup("spi", ...) that
* creates board info from kernel command lines
*/

/*
* scan board_list for spi_board_info which is registered by spi_register_board_info
* 很可惜,s3c24xx的spi驱动中不支持spi_register_board_info这种标准方式注册方式,而是直接调用spi_new_device内部函数
*/

static void __init_or_module
scan_boardinfo(struct spi_master *master)
{
struct boardinfo *bi;
struct device *dev = master->cdev.dev;

down(&board_lock);
list_for_each_entry(bi, &board_list, list) {
struct spi_board_info *chip = bi->board_info;
unsigned n;

for (n = bi->n_board_info; n > 0; n--, chip++) {
if (chip->bus_num != master->bus_num)
continue;
/* some controllers only have one chip, so they
* might not use chipselects. otherwise, the
* chipselects are numbered 0..max.
*/
if (chip->chip_select >= master->num_chipselect
&& master->num_chipselect) {
dev_dbg(dev, "cs%d > max %d\n",
chip->chip_select,
master->num_chipselect);
continue;
}
(void) spi_new_device(master, chip);
}
}
up(&board_lock);
}


/*
* Board-specific early init code calls this (probably during arch_initcall)
* with segments of the SPI device table. Any device nodes are created later,
* after the relevant parent SPI controller (bus_num) is defined. We keep
* this table of devices forever, so that reloading a controller driver will
* not make Linux forget about these hard-wired devices.
*
* Other code can also call this, e.g. a particular add-on board might provide
* SPI devices through its expansion connector, so code initializing that board
* would naturally declare its SPI devices.
*
* The board info passed can safely be __initdata ... but be careful of
* any embedded pointers (platform_data, etc), they're copied as-is.
*/
int __init
spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
struct boardinfo *bi;

bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
if (!bi)
return -ENOMEM;
bi->n_board_info = n;
memcpy(bi->board_info, info, n * sizeof *info);

down(&board_lock);
list_add_tail(&bi->list, &board_list);
up(&board_lock);
return 0;
}


/* On typical mainboards, this is purely internal; and it's not needed
* after board init creates the hard-wired devices. Some development
* platforms may not be able to use spi_register_board_info though, and
* this is exported so that for example a USB or parport based adapter
* driver could add devices (which it would learn about out-of-band).
*/
struct spi_device *__init_or_module
spi_new_device(struct spi_master *master, struct spi_board_info *chip)
{
struct spi_device *proxy;//这个结构很重要,以后就是通过这个结构来操作实际的spi设备的
struct device *dev = master->cdev.dev;
int status;

/* NOTE: caller did any chip->bus_num checks necessary */

if (!spi_master_get(master))
return NULL;

proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
if (!proxy) {
dev_err(dev, "can't alloc dev for cs%d\n",
chip->chip_select);
goto fail;
}
/* 初始化spi_device 结构各成员 */
proxy->master = master;
proxy->chip_select = chip->chip_select;
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
proxy->modalias = chip->modalias;

snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
"%s.%u", master->cdev.class_id,
chip->chip_select);
proxy->dev.parent = dev;
proxy->dev.bus = &spi_bus_type;
proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
proxy->dev.release = spidev_release;

/* drivers may modify this default i/o setup */
/* 调用master->setup(即s3c24xx_spi_setup)函数初始化spi设备 */
status = master->setup(proxy);
if (status <>dev.bus_id, status);
goto fail;
}

/* driver core catches callers that misbehave by defining
* devices that already exist.
*/
status = device_register(&proxy->dev);//真正注册原始设备
if (status <>dev.bus_id, status);
goto fail;
}
dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
return proxy;

fail:
spi_master_put(master);
kfree(proxy);
return NULL;
}


static int s3c24xx_spi_setup(struct spi_device *spi)
{
int ret;
/* 进行一些检查性操作 */
if (!spi->bits_per_word)
spi->bits_per_word = 8;

if ((spi->mode & SPI_LSB_FIRST) != 0)
return -EINVAL;

ret = s3c24xx_spi_setupxfer(spi, NULL);
if (ret <>dev, "setupxfer returned %d\n", ret);
return ret;
}

dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n",
__FUNCTION__, spi->mode, spi->bits_per_word,
spi->max_speed_hz);

return 0;
}


static int s3c24xx_spi_setupxfer(struct spi_device *spi,
struct spi_transfer *t)
{
struct s3c24xx_spi *hw = to_hw(spi);
unsigned int bpw;
unsigned int hz;
unsigned int div;

bpw = t ? t->bits_per_word : spi->bits_per_word;
hz = t ? t->speed_hz : spi->max_speed_hz;

if (bpw != 8) {
dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
return -EINVAL;
}

div = clk_get_rate(hw->clk) / hz;

/* is clk = pclk / (2 * (pre+1)), or is it
* clk = (pclk * 2) / ( pre + 1) */

div = (div / 2) - 1;//求出预分频值

if (div < div =" 1;"> 255)
div = 255;

dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz);
writeb(div, hw->regs + S3C2410_SPPRE);//设置预分频值

spin_lock(&hw->bitbang.lock);
if (!hw->bitbang.busy) {
hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);//修改时钟,先禁用spi
/* need to ndelay for 0.5 clocktick ? */
}
spin_unlock(&hw->bitbang.lock);

return 0;
}


static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
{
struct s3c24xx_spi *hw = to_hw(spi);
unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
unsigned int spcon;

switch (value) {
case BITBANG_CS_INACTIVE:
/* 禁用spi(禁用片选) */
if (hw->pdata->set_cs)
hw->pdata->set_cs(hw->pdata, value, cspol);
else
s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1);
break;

case BITBANG_CS_ACTIVE:
/*
* 启用spi:根据需要设置寄存器并启用使能片选
* (如果spi_board_info中没有设置相应的mode选项的话,那就只能使用默认值SPPIN_DEFAULT和SPCON_DEFAULT了)
*/
spcon = readb(hw->regs + S3C2410_SPCON);

if (spi->mode & SPI_CPHA)
spcon |= S3C2410_SPCON_CPHA_FMTB;
else
spcon &= ~S3C2410_SPCON_CPHA_FMTB;

if (spi->mode & SPI_CPOL)
spcon |= S3C2410_SPCON_CPOL_HIGH;
else
spcon &= ~S3C2410_SPCON_CPOL_HIGH;

spcon |= S3C2410_SPCON_ENSCK;

/* write new configration */

writeb(spcon, hw->regs + S3C2410_SPCON);

if (hw->pdata->set_cs)
hw->pdata->set_cs(hw->pdata, value, cspol);
else
s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol);

break;

}
}

好了,至此spi主控制器(驱动)和板上spi设备注册完毕,以后要使用spi来传输数据的话,只要先获得spi设备结构,然后就可以利用它来和spi驱动打交道了(就好像你要操作一个文件,先要获取文件句柄一样,明白吧^_^)

5 意見:

匿名 说...

Exactly what everyone else has been doing regarding swimwear and consequently precisely what you want to try and do different. [url=http://bikini-wholesale.webnode.com/]China bikini[/url] The actual reason why not a single person is talking over swimwear and as a consequence what one ought to begin doing today. [url=http://wholesale-swimwear1.webnode.com/]sexy swimwears[/url] Short write-up will show you some of the inner workings on swimwear coupled with what you want to handle immediately. [url=http://china-swimwears.webnode.com/]plus size swimwear[/url] Whatever the researchers will never be alleging on the subject off swimwear and in what way this affects you. [url=http://fashion-bikinis.webnode.com/]ladies swimwears[/url] Scarce post provides you with the run information for swimwear that only a few persons know of.
A perfect fix for the bikini that you may understand more about straight away.[url=http://micro-bikini.webnode.com/]selena gomez bikini[/url] Summary article illustrates the proven information about swimwear and the way that it can certainly have an impact on anybody. [url=http://bikini-models.webnode.com/]bikini models[/url] Recent document unearths the low down to bikini in addition , the reasons why you have got to take action now. [url=http://sheer-bikini.webnode.com/]sheer bikini[/url] The fundamentals of bikini available to make use of starting off today. [url=http://thong-bikini.webnode.com/]bikini beach[/url] Neutral guide unwraps 3 great new things surrounding swimwear that nobody is covering. [url=http://extreme-bikini.webnode.com/]slingshot bikini[/url] Fresh new questions regarding swimwear resolved not to mention the reason why you would need to read in detail every single phrase within this article.

匿名 说...

1 particular double turn on swimwear [url=http://plus-size-swimwear.webnode.com/]women s swimwear[/url] Scarce study delivers the small print over bikini that experts claim a few guys are conscious of. [url=http://modest-swimwear.webnode.com/]speedo swimwear[/url] Independent write-up unveil 2 completely new things for bikini that none is mentioning. [url=http://spanx-swimwear.webnode.com/]spanx swimwear[/url] Reason why people are extremely wrong on the subject of swimwear and as a result reasons why you will have to see this review. [url=http://vitamin-a-swimwear.webnode.com/]betsey johnson swimwear[/url] The reason why the whole thing you might have read about swimwear is actually false and exactly what you need be aware of.
New swimwear Book Illustrates Strategy To Rule The swimwear World [url=http://girls-swimwear.webnode.com/]womens swimwear[/url] Most recent questions about swimwear answered not to mention reasons why you should certainly scan through each and every statement within this report. [url=http://freya-swimwear.webnode.com/]freya swimwear[/url] The things the competition actually does on the subject of swimwear and something that that you might want to complete completely different. [url=http://victoria-secret-swimwear.webnode.com/]victoria secret swimwear[/url] Hot swimwear Guide Will show Proven Methods To Dominate The swimwear Scene [url=http://cheap-swimwear.webnode.com/]cheap swimwear[/url] Amazing piece of content exposes the intel on swimwear together with reasons why have got to take action this afternoon.[url=http://women-swimwear.webnode.com/]thong swimwear[/url] Uncommon editorial delivers the important points of swimwear which experts state only a couple of persons are aware of.

匿名 说...

An actual double take on bikini [url=http://plus-size-swimwear.webnode.com/]women s swimwear[/url] Unconventional editorial will give you the run information for bikini which experts claim a few people are aware of. [url=http://modest-swimwear.webnode.com/]modest swimwear[/url] Unprejudiced page presents you with Ten innovative new things concerning bikini that no-one is discussing. [url=http://spanx-swimwear.webnode.com/]vintage swimwear[/url] The actual reason why people are absolute wrong of bikini and consequently the reasons why you have to check out this review. [url=http://vitamin-a-swimwear.webnode.com/]vitamin a swimwear[/url] The reasons why a lot of stuff you may have read about swimwear is simply wrong and what you need to learn.
Cutting edge swimwear Guide Unveil Methods To Dominate The swimwear World [url=http://girls-swimwear.webnode.com/]womens swimwear[/url] Different questions regarding swimwear have been answered and therefore why you must definitely view every single message within this article. [url=http://freya-swimwear.webnode.com/]freya swimwear[/url] Those things that all the others actually does on the subject of swimwear and furthermore what you will need to perform totally different. [url=http://victoria-secret-swimwear.webnode.com/]victoria secret swimwear[/url] Innovative swimwear E-book Uncovers Ideas On How To Dominate The swimwear Scene [url=http://cheap-swimwear.webnode.com/]swimwear sale[/url] Unique guideline unearths the advise around swimwear and the reasons you need to take action right away.[url=http://women-swimwear.webnode.com/]tan through swimwear[/url] Unconventional publishing will give you the run information of swimwear which experts state just a couple of buyers are conscious of.

匿名 说...

For what reason no-one is discussing about swimwear and therefore the thing that you ought to take care of right now. [url=http://high-waisted-swimwear.webnode.com/]high waisted swimwear[/url] Whatever the analysts are generally not discussing over swimwear and also the way it have an effect on you actually. [url=http://discount-swimwear.webnode.com/]women swimwear[/url] Information on how to understand every part there is to find out relating to swimwear in five basic steps. [url=http://modest-swimwear8.webnode.com/]designer swimwear[/url] Contemporary piece of content explains the advise regarding swimwear and as well , the reason why you need to take action now. [url=http://blanca-swimwear.webnode.com/]vintage swimwear[/url] Easiest way to learn every aspect there is to learn around swimwear in Three rather simple steps. [url=http://girls-swimwear0.webnode.com/]girls swimwear[/url]
What scientists usually aren't thinking on the subject off swimwear in a manner that it can affect you. [url=http://string-bikini.webnode.com/]bikini[/url] What the consultants will never be implying about swimwear along with the way it is relevant to you. [url=http://mini-bikini.webnode.com/]thong bikini[/url] Whoa, incredible item. Users gotta take a look at swimwear straight away whilst it is still in stock ! ! [url=http://swimwear-bikinis.webnode.com/]bikinis[/url] Your swimwear-rivals Doesn't Want You To Learn From This strategy [url=http://women-bikinis.webnode.com/]women swimwear[/url] The thing Everybody Ought To Know With Regards To The swimwear Web business [url=http://plus-size-swimwear3.webnode.com/]women swimwear[/url]

匿名 说...

Howcome nobody is mentioning swimwear and what one should create right away. [url=http://high-waisted-swimwear.webnode.com/]high waisted swimwear[/url] What the researchers don't seem to be thinking about swimwear and ways it impacts on you actually. [url=http://discount-swimwear.webnode.com/]ladies swimwear[/url] Practical ideas on how to comprehend every aspect there is to find relating to swimwear in nine simple and easy steps. [url=http://modest-swimwear8.webnode.com/]modest swimwear[/url] Fresh study unveils the low down on the swimwear and then the reasons you must take action immediately. [url=http://blanca-swimwear.webnode.com/]blanca swimwear[/url] The way to learn anything and everything there is to find relating to swimwear in seven basic steps. [url=http://girls-swimwear0.webnode.com/]girls swimwear[/url]
What industry professionals will never be mentioning regarding swimwear and precisely how it have an effect on you actually. [url=http://string-bikini.webnode.com/]mini bikini[/url] What consultants commonly aren't declaring concerning swimwear along with the way it is affecting you. [url=http://mini-bikini.webnode.com/]thong bikini[/url] Whoa, incredible product. Your corporation gotta take a look at swimwear right now whilst it's still in store ! ! [url=http://swimwear-bikinis.webnode.com/]sheer bikini[/url] Your swimwear-competitors Does not Want You To Read These facts [url=http://women-bikinis.webnode.com/]bikinis[/url] The things that Every individual Need To Know About The swimwear Industry [url=http://plus-size-swimwear3.webnode.com/]women swimwear[/url]